前端: 客户前端,客户将数据发给后台,后台将数据存到数据库 管理前端,管理向后台索要数据,后台从数据库查找数据 五、AI编程助手 1、codeium,https://codeium.com/playground 2、codegeex,https://codegeex.cn/zh-CN/playground 3、chatGPT,http://chat.178le.net/index (1)2022年11月30日,美国OpenAI发布的聊天机器人程序 (2)全名:Chat Generative Pre-trained Transformer (3)汉译:人工智能技术驱动的自然语言处理工具 (4)直译:聊天生成的、经过训练的、改革者 (5)Copilot Hub:基于ChatGPT创建个人的知识库AI,app.copilothub.co 一、移动端基础 1、移动端的长度单位 (1)%,相对于父元素的尺寸 (2)em,相对于父字体大小 (3)rem,相对于根字体大小 (4)vw,viewpoint width,视窗宽度,1vw等于视窗宽度的1%,如width: calc(100vw - 260px);font-size: 5vw; (5)vh,viewpoint height,视窗高度,1vh等于视窗高度的1%,如height: calc(100vh - 260px);font-size: 5vh; (6)vmin:vw和vh中较小的那个。做移动页面开发时,如果使用 vw、wh 设置字体大小(比如 font-size: 5vw),在竖屏和横屏状态下显示的字体大小是不一样的。 (7)vmax:vw和vh中较大的那个。vmin或vmax,是当前vw和vh中,较小或较大的那个,用vmin或vmax,使得文字大小在横竖屏下保持一致 附、媒体查询 @media screen and (min-width: 360px) and (max-width: 700px){ padding-left: 15%; } 2、接到新(或别人的)项目时,从以下几个方面入手, (1)根据全图,把握项目整体布局,background、margin、padding及1,2,3层,font-family、font-size1,2,3种 (2)根据全图,把握项目整体逻辑,比如跳转、本地存储的方式(vuex或localStorage)、静态数据的来源(设计稿或后台) (3)代码过程,单图主体-写代码-单图注释-完善代码,重复此步骤 (4)联调 附、左右居中(换行也可以) <div class="center"> <div><img src=""/></div> <div></div> <div></div> <div></div> </div> .center{ display: flex; flex-direction: column; //align-item: center;//换行不居中 text-align: center;//换行居中 } 3、问题与解决 (1)iPhone12pro max,跳到新网页,新网页的位置没到顶, 原因:跳转前的网页没到顶,浏览器把前网页的位置用在后网页上; 解决:document.body.scrollTop=0;document.documentElement.scrollTop=0; 三、uniapp跨端框架 来源,https://gitee.com/dcloud/uni-app/tags?page=60 来源,https://uniapp.dcloud.net.cn/history.html 1、uniapp的产生背景 (1)2012年,DCloud开始研发小程序技术,推出了HBuilder开发工具 (2)2015年,DCloud商用了小程序技术,命名“流应用”,并将该技术标准捐给工信部,同时推进各家流量巨头接入该标准,众多开发者用该标准为“流应用”平台提供应用,供用户下载 (3)2015年9月,DCloud推进微信团队开展小程序业务 (4)2016年初,微信团队决定上线微信小程序业务,订制了自己的标准,随后包括手机厂商在内的各大流量巨头,陆续上线类似微信小程序的业务 (5)DCloud用自己的开发工具HBuilder、自己的开发框架uni-app为开发者抹平“各平台”的差异,让“一套代码”在“各APP”的客户端运行,由标准的提供者转向标准的汇总者 (6)微信开发工具开发的小程序只能在微信上运行,HBuilder用uni-app开发的小程序能在所有应用上运行,https://uniapp.dcloud.net.cn/ 2、uni-app的版本发布 (1)2018年8月,uni-app1.0.0 版本发布, (2)2021年9月,uni-app2.0.0 版本发布, (3)2023年1月,uni-app3.0.0 版本发布, 3、uni-app的相关内容 (1)uni小程序SDK,是DCloud开发的原生SDK,提供Android、iOS两个版本,需要集成到原生工程中,使APP的服务端能运行用uni-app框架开发的小程序 (2)uniCloud,基于serverless的云开发平台,为开发者提供免费服务器,由DCloud、阿里云、腾讯云三者联合实现 (3)Uni,统一的,读you ni (4)SDK,软件开发工具包 4、与“uniapp跨端框架”相似内容,混合类解决方案(Hybrid、RN、 flutter等) 四、vant-ui相关 1、<input type="value"> (1)button,定义可点击按钮(多数情况下,用于通过 JavaScript 启动脚本) (2)checkbox,定义复选框 (3)file,定义输入字段和 "浏览"按钮,供文件上传 (4)hidden,定义隐藏的输入字段 (5)image,定义图像形式的提交按钮 (6)password,定义密码字段,该字段中的字符被掩码 (7)radio,定义单选按钮 (8)reset,定义重置按钮,重置按钮会清除表单中的所有数据 (9)submit,定义提交按钮,提交按钮会把表单数据发送到服务器 (10)text,定义单行的输入字段,用户可在其中输入文本,默认宽度为 20 个字符 2、深度选择器 当<style scoped>只作用于当前组件中的元素,可采用下列方式影响到子组件 (1)全局样式 <style> .wrap .child { color: red; } </style> (2)本页样式 >>> <style scoped> .wrap >>> .child { color: red; } </style> (3)本页样式 /deep/ <style scoped> .wrap /deep/ .child { color: red; } </style> 3、vant-ui动态内容 (1)toast 轻提示,没有遮罩,页面居中显示,无样式变化,3秒后自动消失 (2)notify 消息提示,没有遮罩,页面顶部显示,有样式变化,3秒后自动消失 (3)NoticeBar 通知栏,没有遮罩,固定位置显示,有样式变化,不消失 (4)Popover 气泡弹出框,没有遮罩,常用于点击处显示,常用于下拉选项 (5)overlay 遮罩层,全屏罩住 (6)popup 弹出层,有遮罩,常用触底显示,确认后消失,常用于省市县、日期选择 (7)dialog 弹出框,有遮罩,常用居中显示,确认后消失 4、van-field (1)输入框,正常 (2)文本框,type="textarea" (3)下拉框的逻辑 输入框禁用,右侧添加三角, 点击事件让下方气泡出现、传出序号、计算-从总数据中找出的相关数据-成下拉选项, 点击事件从自身数据中找出的相关数据-成为下拉选项,气泡出现 点击确定时,给对应的v-model赋值,气泡消失 (4)其它,用插槽input, 自定义输入框,使用此插槽后,与输入框相关的属性和事件将失效 在Form组件进行表单校验时,会使用input插槽中子组件的value,而不是Field组件的value (5)<van-uploader/>的部分属性 capture,图片选取模式,可选值为camera,直接调起摄像头 after-read,文件读取完成后的回调函数 before-read,文件读取前的回调函数,返回false可终止文件读取,支持返回Promise 4、Rule数据结构,只有一个对象项的数组 (1)required,是否为必选字段,boolean (2)message,错误提示文案 (3)trigger,本项规则的触发时机,可选值为onChange、onBlur (4)formatter,格式化函数,将表单项的值转换后,再用“pattern”或“validator”进行校验 (5)pattern,通过正则表达式进行校验,返回值为false时,红色的message出现在输入框的下方 (6)validator,通过函数进行校验,返回值为false时,机制让红色的message出现在输入框的下方; 返回值为promise实例时,机制向其注入resolve、reject,在reject里让红色的message出现在输入框的下方 validator:function(rule, val, callback) { return new Promise(function(resolve, reject) { setTimeout(function() { const dataNum = Date.now() if (dataNum % 2 === 0) { resolve('成功') } else { reject('失败') } }, 2000) }) } 5、插槽input示例 (1)html部分 <van-form @submit="beforeSubmit" ref="form"> <template v-for="(item,idx) in formList"> <div class="sign-form" :key="idx" v-if="item.inputType == 0"> <van-field name="name" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" show-word-limit :label="item.topicName" v-model="formData[idx]" :placeholder="'请输入'+item.topicName" :maxlength="item.numLimit" /> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 1"> <van-field rows="4" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" autosize v-model="formData[idx]" :label="item.topicName" type="textarea" show-word-limit /> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 2"> <van-field :label="item.topicName" v-model="formData[idx]" right-icon="arrow-down" readonly placeholder="请选择" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" @click="changeCol(idx)" /> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 3 && item.isCheckbox == 0"> <van-field :label="item.topicName" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]"> <template #input> <van-radio-group v-model="formData[idx]" direction="horizontal" class="hor-style"> <van-radio v-for="(v,k) in JSON.parse(item.optionInfo)" :name="v.option" :key="k">{{v.option}}</van-radio> </van-radio-group> </template> </van-field> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 3 && item.isCheckbox == 1"> <van-field :label="item.topicName" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]"> <template #input> <van-checkbox-group v-model="formData[idx]" :max="item.selectLimitMax ? item.selectLimitMax : 0" direction="horizontal"> <van-checkbox v-for="(value,key) in JSON.parse(item.optionInfo)" :name="value.option" shape="square" :key="key">{{value.option}}</van-checkbox> </van-checkbox-group> </template> </van-field> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 4"> <div class="van-form_card"> <div class="field__label">{{item.topicName}}</div> <div class="field__desc">支持“图片”扩展名:png、gif、jpeg、pcx、psd、tiff</div> </div> <van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" v-model="formData[idx]"> <template #input> <div class="upload-preview"> <van-image v-if="formData[idx]" width="4rem" height="3rem" fit="contain" :src="formData[idx]" /> <van-uploader :before-read="uploadFile" accept="image/png,image/gif,image/jpeg,image/pcx,image/psd,image/tiff" :name="idx"> <van-icon name="plus" /> </van-uploader> </div> </template> </van-field> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 5"> <div class="van-form_card"> <div class="field__label">{{item.topicName}}</div> <div class="field__desc">支持“视频”扩展名:avi、MP4、rmvb</div> </div> <van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请输入正确内容',index:idx }]" v-model="formData[idx]"> <template #input> <div class="flex-col"> <div class="video-upload" v-if="showUpload"> <span>视频上传中...</span> <van-progress :show-pivot="false" :percentage="videoUploadPercent" /> </div> <span class="link" v-if="formData[idx]" @click="href(idx)">{{videoName[idx]}}</span> <van-uploader :before-read="uploadVideo" accept="*" v-if="!showUpload" :name="idx"> <van-button icon="plus" type="primary">上传视频</van-button> </van-uploader> </div> </template> </van-field> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 6"> <div class="van-form_card"> <div class="field__label">{{item.topicName}}</div> <div class="field__desc">支持“文件”扩展名:doc、docx、txt、pdf、pptx、ppt、xlsx、xls</div> </div> <van-field name="name" type="hidden" :rules="[{ validator: valiFormData, message: '请选择',index:idx }]" v-model="formData[idx]"> <template #input> <div class="flex-col"> <span class="link" v-if="formData[idx]" @click="href(idx)">{{formData[idx]}}</span> <van-uploader :before-read="uploadFile" accept=".doc, .docx, .txt, .pdf, .pptx, .ppt, .xlsx, .xls" :name="idx"> <van-button icon="plus" type="primary">上传文档</van-button> </van-uploader> </div> </template> </van-field> </div> <div class="sign-form" :key="idx" v-if="item.inputType == 7"> <van-field readonly @click="clickDatePicker(idx)" name="name" :rules="[{ validator: valiFormData, message: '请选择日期',index:idx }]" :label="item.topicName" v-model="formData[idx]" :placeholder="'请选择'+item.topicName" /> <van-popup v-model="showDatePicker" position="bottom"> <van-picker show-toolbar title="选择日期" :columns="dateCol" @cancel="showDatePicker = false" @confirm="dateConfirm" /> </van-popup> <!-- van-popup默认在兄级加蒙层van-overlay,若没有出现,可能有人在项目的全局给清除了 --> </div> </template> <div class="vt-foot "> <van-button :loading="loading" loading-text="保存中..." native-type="submit" block color="#fdb235">提交</van-button> <!-- native-type,原生button标签的type属性,表单内点击此按钮,自动触发表单的onsubmit事件 --> <!-- loading,设置按钮为加载状态,加载状态下默认会隐藏按钮文字 --> <!-- loading-text,设置加载状态下的文字 --> <!-- confirm函数会弹出一个带有确定和取消按钮的对话框,点击确定返回true,点击取消返回false --> <!-- alert函数只有一个确定按钮,点击确定后对话框消失,没有返回值 --> </div> </van-form> (2)js部分 A、上传图片 uploadFile(file, detail) { let formData = new FormData(); formData.append('file', file); axios.post(this.$upload, formData, { 'Content-Type': 'multipart/form-data' }) .then(res => { if (res.data && res.data.code === 10000) { this.formData[detail.name] = res.data.data; let temp = res.data.data; this.formData.splice(detail.name, 1, temp); } else { this.$dialog.alert({ title: '提示', message: '上传文件失败', theme: 'round-button', }) .then(() => { // on close }); } }) }, B、上传视频 来源,https://help.aliyun.com/document_detail/383952.html import OSS from "ali-oss"; // 开放存储服务(OpenStorageService,简称OSS),是阿里云对外提供的海量,安全,低成本,高可靠的云存储服务。 // 用户可以通过简单的API(REST方式的接口),在任何时间、任何地点、任何互联网设备上进行数据上传和下载。 <van-uploader accept="*" v-if="!showUpload" :name="idx" :before-read="uploadVideo"> <van-button icon="plus" type="primary">上传视频</van-button> </van-uploader> uploadVideo(file, detail) { let type = file.name.substring(file.name.lastIndexOf(".") + 1) .toLowerCase() if (this.videoType.indexOf(type) < 0 || file.type.indexOf("video") < 0) { this.$dialog.alert({ title: '提示', message: '仅支持 .avi, .mp4, .rmvb, .mov 格式的视频', theme: 'round-button', }); return; } let max = 1024 * 1024 * 1024; if (file.size > max) { this.$dialog.alert({ title: '提示', message: '上传视频大小不能超过 1G!', theme: 'round-button', }) .then(() => {}); return; } myRequest({ tokenName: "ios", }) .then(data => { let client = new OSS({ region: "oss-cn-beijing", accessKeyId: data.data.data.accessKeyId, accessKeySecret: data.data.data.accessKeySecret, bucket: data.data.data.bucketName, stsToken: data.data.data.securityToken, }); const suffix = file.name.substr(file.name.indexOf(".")); let fileUrl = `test/${new Date().getTime()}${suffix}`; client .multipartUpload(fileUrl, file, { progress: (p) => { this.videoUploadPercent = Math.round(p * 100); this.showUpload = true; }, partSize: 102400, }) .then((res) => { this.showUpload = false; this.videoName[detail.name] = res.name; let url = res.res.requestUrls[0]; this.formData[detail.name] = url.substring(0, url.indexOf("?")); let temp = this.formData[detail.name]; this.formData.splice(detail.name, 1, temp); }) .catch((err) => { this.showUpload = false; console.log(err); this.$dialog.alert({ title: '提示', message: '上传失败', theme: 'round-button', }) }); }) } 二、微信小程序-账号与代码管理 1、微信公众平台,https://mp.weixin.qq.com/ (1)账号分类(四种),服务号(解答用户提问,每月可群发4次)、订阅号(向用户提供资讯,每天可群发1次)、小程序(免关注,免订阅,扫码即用,用完即退)、企业微信(原企业号,用于企业办公管理) (2)注册,小程序-测试号-游戏号&其它号的注册流程,公众平台-小程序图标(查看详情)-前往注册-立即申请-扫码(即可获得游戏号&其它号) (3)注册,小程序-普通号-游戏号/其它号的注册流程,公众平台-小程序图标(查看详情)-前往注册-注册(账号信息)-邮箱激活-信息登记-添加类目-各种服务/工具/体育/游戏 (4)登录,APP扫描公众平台的二维码,选择其中一个账号登录 (5)开发,小程序-开发文档,https://developers.weixin.qq.com/miniprogram/dev/framework/ (6)开发,小程序-开发工具,https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html 2、账号, (1)小程序普通号 AppID(小程序ID),wx209859 原始ID,gh_9b058 (2)小程序git账户 用户名:1371 密码:4195 (3)小程序域名 服务器域名(第三方数据库的数据) 业务域名(自己数据库的数据) (4)小程序测试号 AppID(小程序ID),wxbdb0903 AppSecret(小程序密钥),d0b0452d67d04 (5)小游戏测试号 AppID(小程序ID),wxad135a AppSecret(小程序密钥),2fd7568502 3、项目,https://git.weixin.qq.com (1)创建项目,项目(组)-创建项目(组),https://git.weixin.qq.com/138/xiau1.git (2)项目下载与上传, ====项目为空时,会有以下内容 项目初始化git命令行 ====以下,git全局设置 git config --global user.name "Z_北京码农_钱成" git config --global user.email "[email protected]" ====以下,创建一个新的版本库(用命令克隆-线上版本库的项目,进行开发,推送) git clone https://git.weixin.qq.com/138/xiau1.git(连接远程、克隆) cd xiangmuzu1 touch README.md git add README.md git commit -m "add README" git push -u origin master(推送到远程master分支) ====以下,现有的文件夹或Git版本库(用现有的文件夹或下载的版本库文件夹-与-线上版本库的项目-关联,进行开发,推送。如现有的文件夹里没有分支,只能推送到master分支) cd existing_folder git init git remote add origin https://git.weixin.qq.com/138/xiau1.git(连接远程) git add . git commit -m "add README" git push -u origin master(推送到远程master分支) (3)代码管理 开发文档,开发-工具-开发辅助-微信开发者·代码管理 开发工具,工具-微信开发者·代码管理 删除仓库,管理后台(https://git.weixin.qq.com/)-项目-您的项目-XXXXX-设置-高级设置-仓库设置-删除项目 删除仓库,管理后台(https://git.weixin.qq.com/13/path2)-设置-高级设置-仓库设置-删除项目 删除项目组,管理后台(https://git.weixin.qq.com/)-项目组-XXXXX-设置-删除。内置的项目组无法删除 (4)版本管理, 开发工具-上传 微信公众平台-登录微信小程序-管理-版本管理-开发版本/发布 三、微信小程序-目录结构 来源,开发-指南-目录结构 来源,https://developers.weixin.qq.com/miniprogram/dev/framework/structure.html 1、一个小程序主体部分由三个文件组成,必须放在项目的根目录 (1)app.js,小程序全局逻辑 (2)app.json,小程序全局配置 (3)app.wxss,小程序全局样式表 2、一个小程序页面由四个文件组成 (1).js,页面逻辑 (2).wxml,页面结构 (3).json,页面配置 (4).wxss,页面样式表 四、微信小程序-框架 来源,开发-指南-小程序框架 来源,https://developers.weixin.qq.com/miniprogram/dev/framework/MINA.html 1、框架 (1)介绍 框架,在视图层-与-逻辑层间提供了数据传输-和-事件系统,让开发者能够专注于数据与逻辑 页面管理,框架管理页面路由,做到无缝切换,给以生命周期,开发者将页面的数据、方法、生命周期函数注册到框架中即可 数据绑定,让数据与视图保持同步 基础组件 丰富的API (2)场景值,描述用户进入小程序的路径 (3)逻辑层,介绍、注册小程序、注册页面、页面生命周期、页面路由(页面栈表现、触发时机)、模块化、API(事件监听、同步、异步、异步返回Promise、云开发) (4)视图层,介绍、WXML、WXSS样式、WXS脚本语言、事件系统(介绍、WXS响应事件)、简易双向绑定、基础组件、获取界面上的节点信息、响应显示区域变化、分栏模式、动画、初始渲染缓存 2、事件系统, (1)什么是事件 事件是视图层到逻辑层的通讯方式 事件可以将用户的行为反馈到逻辑层进行处理 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数 事件对象可以携带额外信息,如id,dataset,touches (2)事件的使用方式,在组件中绑定一个事件处理函数 示例一: <view id="tapTest" data-hi="Weixin" bindtap="tapName"> Click me! </view> Page({ tapName: function(event) { console.log(event) } }) 示例二: <wxs module="wxs" src="./test.wxs"></wxs> <view id="tapTest" data-hi="Weixin" bindtap="{{wxs.tapName}}"> 绑定的WXS函数必须用{{}}括起来 </view> 以下test.wxs function tapName(event, ownerInstance) { console.log('tap Weixin', JSON.stringify(event)) } module.exports = { tapName: tapName } (3)事件捕获与冒泡,先捕获后冒泡 冒泡从里向外 bind,绑定事件,向上冒泡,后可以紧跟一个冒号,其含义不变,如bind:tap catch,绑定事件,阻止向上冒泡 mut-bind,绑定事件,向上冒泡,与上级mut-bind“互斥”的,上级mut-bind不会被触发,上级的其它绑定依然会触发 捕获从外向里 capture-bind,捕获 capture-catch,中断捕获、取消冒泡 以下,冒泡与阻止冒泡,点击inner view会先后调用handleTap3和handleTap2 <view id="outer" bindtap="handleTap1"> outer view <view id="middle" catchtap="handleTap2"> middle view <view id="inner" bindtap="handleTap3"> inner view </view> </view> </view> 以下,互斥事件,点击inner view会先后调用handleTap3和handleTap2,点击middle view会调用handleTap2和handleTap1 <view id="outer" mut-bind:tap="handleTap1"> outer view <view id="middle" bindtap="handleTap2"> middle view <view id="inner" mut-bind:tap="handleTap3"> inner view </view> </view> </view> 以下,事件的捕获阶段,点击inner view会先后调用handleTap2、handleTap4、handleTap3、handleTap1 <view id="outer" bind:touchstart="handleTap1" capture-bind:touchstart="handleTap2"> outer view <view id="inner" bind:touchstart="handleTap3" capture-bind:touchstart="handleTap4"> inner view </view> </view> 如果将上面代码中的第一个capture-bind改为capture-catch,将只触发handleTap2 (4)事件对象,如无特殊说明,当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象。 BaseEvent 基础事件对象属性列表 type,代表事件的类型 timeStamp,页面打开到触发事件所经过的毫秒数 target,触发事件的源组件 id,事件源组件的id dataset,事件源组件上由data-开头的自定义属性组成的集合 currentTarget,事件绑定的当前组件 id,当前组件的id dataset,当前组件上由data-开头的自定义属性组成的集合 mark,识别具体触发事件的target节点,承载一些自定义数据,类似于dataset <view mark:myMark="last" bindtap="bindViewTap"> <button mark:anotherMark="leaf" bindtap="bindButtonTap">按钮</button> </view> 在上述WXML中,如果按钮被点击,将触发bindViewTap和bindButtonTap两个事件,事件携带的event.mark将包含myMark和anotherMark两项 Page({ bindViewTap: function(e) { e.mark.myMark === "last" // true e.mark.anotherMark === "leaf" // true } }) mark,会包含从触发事件的节点到根节点上所有的mark属性值 dataset,仅包含一个节点的data-属性值。 CustomEvent 自定义事件对象属性列表(继承 BaseEvent) detail,额外的信息 TouchEvent 触摸事件对象属性列表(继承 BaseEvent) touches,触摸事件,当前停留在屏幕中的触摸点信息的数组,每个元素为一个Touch对象,表示当前停留在屏幕上的触摸点 identifier,触摸点的标识符 pageX/pageY,距离文档左上角的距离,文档的左上角为原点 ,横向为X轴,纵向为Y轴 clientX/clientY,距离页面可显示区域(屏幕除去导航条)左上角距离,横向为X轴,纵向为Y轴 changedTouches,触摸事件,当前变化的触摸点信息的数组 (5)WXS响应事件 问题,有频繁用户交互的效果,产生了频繁的视图层与逻辑层交互,使小程序卡顿 解决,用WXS函数响应小程序事件,目前只能响应内置组件的事件,不支持自定义组件事件 以下,代码示例 <wxs module="test" src="./test.wxs"></wxs> <view change:prop="{{test.propObserver}}" prop="{{propValue}}" bindtouchmove="{{test.touchmove}}" class="movable"></view> change:prop,prop属性被设置的时候触发WXS函数 //test.wxs module.exports = { touchmove: function(event, instance) {}, propObserver: function(newValue, oldValue, ownerInstance, instance) {} //以下参数的解释可能有问题 //event.instance、ownerInstance,表示触发事件的组件的 ComponentDescriptor 实例 //instance,表示触发事件的组件所在的组件的 ComponentDescriptor 实例,一般是页面实例 } 以下,ComponentDescriptor的属性示例,共有13个 方法,selectComponent;参数,selector对象;描述,返回组件的ComponentDescriptor实例 方法,selectAllComponents;参数,selector对象数组;描述,返回组件的ComponentDescriptor实例数组 3、简易双向绑定,自定义组件将自身的myValue属性双向绑定到了组件内输入框的value属性上 custom-component定义,<input model:value="{{myValue}}" /> custom-component使用,<custom-component model:my-value="{{pageValue}}" /> 4、基础组件 5、获取界面上的节点信息 (1)WXML节点信息 const query = wx.createSelectorQuery() query.select('#the-id').boundingClientRect(function(res){ res.top // #the-id 节点的上边界坐标(相对于显示区域) }) query.selectViewport().scrollOffset(function(res){ res.scrollTop // 显示区域的竖直滚动位置 }) query.exec() (2)WXML节点布局相交状态 以下,目标节点(用选择器 .target-class 指定)每次进入或离开页面显示区域时,触发回调函数 Page({ onl oad: function(){ wx.createIntersectionObserver().relativeToViewport().observe('.target-class', (res) => { res.id // 目标节点 id res.dataset // 目标节点 dataset res.intersectionRatio // 相交区域占目标节点的布局区域的比例 res.intersectionRect // 相交区域 res.intersectionRect.left // 相交区域的左边界坐标 res.intersectionRect.top // 相交区域的上边界坐标 res.intersectionRect.width // 相交区域的宽度 res.intersectionRect.height // 相交区域的高度 }) } }) 以下,目标节点(用选择器.target-class指定)与参照节点(用选择器.relative-class指定)在页面显示区域内相交或相离,且相交或相离程度达到目标节点布局区域的20%和50%时,触发回调函数 Page({ onl oad: function(){ wx.createIntersectionObserver(this, { thresholds: [0.2, 0.5] }).relativeTo('.relative-class').relativeToViewport().observe('.target-class', (res) => { res.intersectionRatio // 相交区域占目标节点的布局区域的比例 res.intersectionRect // 相交区域 res.intersectionRect.left // 相交区域的左边界坐标 res.intersectionRect.top // 相交区域的上边界坐标 res.intersectionRect.width // 相交区域的宽度 res.intersectionRect.height // 相交区域的高度 }) } }) 6、响应显示区域变化 (1)one.json,手机单页面启用屏幕旋转支持 { "pageOrientation": "auto", } (2)app.json,iPad上启用屏幕旋转支持、 Windows/Mac 上启用大屏模式 { "resizable": true, } (3)Media Query媒体查询 .my-class { width: 40px; } @media (min-width: 480px) { /* 仅在 480px 或更宽的屏幕上生效的样式规则 */ .my-class { width: 200px; } } (4)屏幕旋转事件 Page({ onResize(res) { res.size.windowWidth // 新的显示区域宽度 res.size.windowHeight // 新的显示区域高度 } }) Component({ pageLifetimes: { resize(res) { res.size.windowWidth // 新的显示区域宽度 res.size.windowHeight // 新的显示区域高度 } } }) 7、分栏模式,启用分栏模式,在app.json中同时添加代码 { "resizable": true, "frameset": true } 8、动画 (1)用法,this.animate(selector, keyframes, duration, callback) (2)示例 this.animate( '#container', [ { opacity: 1.0, rotate: 0, backgroundColor: '#FF0000' }, { opacity: 0.5, rotate: 45, backgroundColor: '#00FF00'}, { opacity: 0.0, rotate: 90, backgroundColor: '#FF0000' }, ], 5000, function(){ this.clearAnimation('#container', { opacity: true, rotate: true }, function () { console.log("清除了#container上的opacity和rotate属性") }) }.bind(this) ) 9、初始渲染缓存 (1)初始渲染 逻辑层初始化:载入必需的小程序代码、初始化页面this对象、将相关数据发送给视图层。 视图层初始化:载入必需的小程序代码,然后等待逻辑层初始化完毕,接收逻辑层发送的数据,渲染页面 在启动页面时,尤其是小程序冷启动、进入第一个页面时,逻辑层初始化的时间较长 (2)初始渲染缓存 在小程序页面第一次被打开后,将页面初始数据渲染结果记录下来,写入一个持久化的缓存区域 在这个页面被第二次打开时,检查缓存中是否还存有这个页面上一次初始数据的渲染结果,如果有,就直接将渲染结果展示出来 如果展示了缓存中的渲染结果,这个页面暂时还不能响应用户事件,等到逻辑层初始化完毕后才能响应用户事件 复杂组件不能被展示或不能响应交互 (3)初始渲染缓存的作用 快速展示出页面中永远不会变的部分,如导航栏 预先展示一个骨架页,提升用户体验 展示自定义的加载提示 提前展示广告 (4)静态初始渲染缓存示例 以下,one.json,单页初始渲染缓存 { "initialRenderingCache": "static" } 以下,app.json,所有页初始渲染缓存 { "window": { "initialRenderingCache": "static" } } 以下,静态页面 <view wx:if="{{loading}}">正在加载</view> 以下,正确的做法 Page({ data: { loading: true } }) 以下,错误的做法 Page({ data: {}, onl oad: function() { this.setData({ loading: true }) } }) (5)静态初始渲染缓存,慎用
标签:git,17,res,程序,事件,移动,data,页面 From: https://www.cnblogs.com/gushixianqiancheng/p/17412155.html