摘要:小程序自定义组件开发规范一个小程序组件由个文件组成,分别是,本规范只关注组件的,其它自行查看官方文档。的变量可以分为以下种类型组件外部通过组件属性的方式传入内部的数据。
小程序自定义组件开发规范
一个小程序组件由4个文件组成,分别是wxml、wxss、json、js,本规范只关注组件的js,其它自行查看官方文档。
在自定义组件的 js 文件中,需要使用 Component() 来注册组件,Component是一个构造器,可用于定义组件,调用Component构造器时可以指定组件的属性、数据、方法等。
Component的变量可以分为以下2种类型:
properties:组件外部通过组件属性的方式传入内部的数据。
可用于wxml渲染
不能做会修改数据的运算操作,如果必须要修改数据,可以先把数据赋值给组件的data,例如:this.data.a = this.properties.a,再去做运算操作,有以下两种情况:
如果this.properties.a的数据是基本数据类型,则直接赋值
如果this.properties.a的数据是引用数据类型,则需要深拷贝一个新的数据之后,再赋值
data:组件内部声明的数据
主要用于wxml渲染
可以做任何的运算符操作
Component的函数可以分为以下几种类型:
life-cycle-function:组件生命周期函数
event-function:在组件的methods下自定义的事件响应函数,与wxml的事件绑定一一对应
commen-function:在组件的methods下自定义的公共函数,供life-cycle-function与event-function调用
request-function:在组件的methods下自定义的异步请求数据的函数
在实际的代码中,我们利用注释把变量和函数分为以上定义的几种类型。
下面以小程序的语音消息组件为例:
文件路径:components/voice-message
import { isCorrectVal } from "../../utils/index"; const app = getApp(); Component({ properties: { // work:作业的语音 comment:评论的语音 type: { type: String, value: "work" }, // 语音的地址 voiceUrl: { type: String, value: "" }, // 音频的长度 voiceLength: { type: Number, value: 0 } }, data: { unsubscribe: function() {}, model: { loading: false, render: false, id: 0, voiceLength: 0, innerAudioContext: null, playing: false, trumpetStatus: [false, false, true], btnLength: "0" } }, /** * life-cycle-function * @description 初始化组件 */ attached: function() { this.data.unsubscribe = app.soundScheduler.subscribe( "beforePlay", () => { this.data.model.innerAudioContext.stop(); } ); if (!isCorrectVal(this.properties.voiceUrl)) { throw new Error("音频地址错误"); } /* 计算音频按钮长度 */ let base = 40; // 10s内基础长度 let step = 20; // 每10s增加的长度 let stepNum = 0; let length = 40; // 按钮初始长度 if (this.properties.type === "comment") { base = 30; step = 15; length = 30; } if (this.properties.voiceLength > 10) { stepNum = Math.ceil((this.properties.voiceLength - 10) / 10); } length = base + step * stepNum; this.setData({ "model.btnLength": length, "model.voiceLength": this.properties.voiceLength >= 2 ? this.properties.voiceLength : 2 }); this.data.model.innerAudioContext = wx.createInnerAudioContext(); this.data.model.innerAudioContext.obeyMuteSwitch = false; this.data.model.innerAudioContext.src = this.properties.voiceUrl; this.data.model.innerAudioContext.onPlay(() => { this.onPlay(); }); this.data.model.innerAudioContext.onStop(res => { this.onStop(); }); this.data.model.innerAudioContext.onEnded(res => { this.onStop(); }); this.data.model.innerAudioContext.onError(res => { this.onError(res); }); }, methods: { /** * event-function * @description 切换音频播放状态(播放/停止) */ togglePlay: function() { if (this.data.model.loading) return; if (this.data.model.playing) { this.data.model.innerAudioContext.stop(); } else { this.setData( { "model.loading": true }, () => { app.soundScheduler.dispatch("beforePlay"); app.videoContext.pause(); this.data.model.innerAudioContext.play(); setTimeout(() => { if (this.data.model.loading) { this.setData({ "model.loading": false }); } }, 3000); } ); } }, /** * common-function * @description 音频开始播放触发时的处理函数 */ onPlay: function() { this.setData( { "model.loading": false }, () => { this.running(); } ); }, /** * common-function * @description 音频停止播放或者播放结束时的处理函数 */ onStop: function() { this.stop(); }, /** * common-function * @description 音频播放错误时的处理函数 */ onError: function(res) { console.log(res); this.setData( { "model.loading": false }, () => { this.stop(); } ); }, /** * common-function * @description 启动音频小喇叭动画 */ running: function() { let vm = this; vm.data.model.playing = true; let num = 1; let idx = 1; let timer = null; function animation() { if (!vm.data.model.playing) { clearTimeout(timer); vm.setData({ "model.trumpetStatus": [false, false, true] }); return; } switch (idx) { case 1: vm.setData({ "model.trumpetStatus": [true, false, false] }); break; case 2: vm.setData({ "model.trumpetStatus": [false, true, false] }); break; case 3: vm.setData({ "model.trumpetStatus": [false, false, true] }); break; } ++idx; if (idx === 4) { idx = 1; } ++num; timer = setTimeout(animation, 600); } timer = setTimeout(animation, 600); }, /** * common-function * @description 停止音频小喇叭动画 */ stop: function() { this.data.model.playing = false; } }, /** * life-cycle-function * @description 卸载组件 */ detached: function() { this.data.model.innerAudioContext.stop(); this.data.unsubscribe(); }, });
如果你已经看完了代码,那么对这个组件的 代码执行过程 是否心里已经有数?
这个组件的代码执行过程是这样的:
1. 在生命周期钩子函数attached中初始化组件 2. 组件挂载并渲染完成,到达可响应用户操作的状态(这个步骤由小程序自动执行,无需写额外的代码) 3. 响应用户操作 - 用户点击语音消息,如果语音没在播放,则播放语音 - 用户点击语音消息,如果语音正在播放,则停止播放 4. 卸载组件
如果心里还没数,那把除了life-cycle-function和events-function的之外的代码都忽略掉,再看看组件生命周期钩子函数和用户交互事件响应函数的代码与注释呢?
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/108000.html
摘要:背景由于有赞与微信密切的合作关系,我们第一时间就拿到了内测账号。春节前我们把它开源到了上,是希望帮助开发者尤其是有赞生态的开发者能够更快更低门槛地开发出自己的微信小程序,同时希望和开发者们一起打造高颜值好用易扩展的小程序组件库。 背景 由于有赞与微信密切的合作关系,我们第一时间就拿到了内测账号。17年1月9号,我们同时上线了有赞微商城小程序和有赞精选小程序(可以在微信-发现-小程序里搜...
摘要:传统的网页编程采用的三剑客来实现,在微信小程序中同样有三剑客。观察者模式不难实现,重点是如何在微信小程序中搭配其特有的生命周期来使用。交互事件传统的事件传递类型有冒泡型与捕获型,微信小程序中自然也有。 本文由作者邹永胜授权网易云社区发布。 简介为了更好的展示我们即时通讯SDK强悍的能力,网易云信IM SDK微信小程序DEMO的开发就提上了日程。用产品的话说就是: 云信 IM 小程序 S...
阅读 3479·2023-04-25 15:52
阅读 551·2021-11-19 09:40
阅读 2525·2021-09-26 09:47
阅读 985·2021-09-22 15:17
阅读 3508·2021-08-13 13:25
阅读 2149·2019-08-30 15:56
阅读 3436·2019-08-30 13:56
阅读 2073·2019-08-30 11:27