引用组件
局部引用:页面的.josn文件中
"usingComponents": { "my-test1": "/components/test/test"}
全局引用: app.json
中配置
全局引用vs局部引用:
如果某个组件在多个页面当中都用到了,就全局引用
如果只在特定的页面中才使用,就局部引用
组件和页面的.js与.json文件有明显的不同
“component”: true
属性Component()
函数methods
节点中组件样式隔离的注意点:
app.wxss
全局样式里面的样式,对组件是无效
只有class选择器会有样式隔离效果,id选择器、属性选择器、标签选择器不受样式隔离的影响。
有时候 我们希望在外界能够控制组件内部的样式,此时可以通过stylelsolation
修改组件的样式隔离选项,用法如下:
{ "styleIsolation": "isolated" }
properties
属性
在小程序组件中,properties
是组件的对外属性,用来接收外界传递到组件当中的数据,
实例代码如下:
Component({
// 属性定义
properties: {
max: { // 完整定义属性的方式
type: Number, // 属性值的数据类型
value: 10 // 属性默认值
},
max: Number //简化定义属性方式
}
})
<my-test1 max="20"> <my-test1>
在小程序里面,两者都是可读可写的
data更倾向于存储组件的私有数据
properties更倾向于存储外界传递到组件中的数据
由于data数据和properties属性在本质上没有任何区别,因此properties属性也可以用于页面渲染,或使用setData为properties中的属性重新赋值。
组件的.wxml
<!--components/test/test.wxml-->
<view>{{n1}} + {{n2}} = {{sum}}</view>
<button size="mini" bindtap="addN1" type="primary">n1自增</button>
<button size="mini" bindtap="addN2">n2自增</button>
// components/test/test.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
n1: 0,
n2: 0,
sum: 0
},
/**
* 组件的方法列表
*/
methods: {
addN1() {
this.setData({
n1: this.data.n1 + 1
})
},
addN2() {
this.setData({
n2: this.data.n2 + 1
})
}
},
observers: {
'n1, n2': function(n1, n2) {
this.setData({
sum: n1 + n2
})
}
}
})
app.json
中
"usingComponents": { "my-test2": "/components/test2/test2" }
test2.wxml
<!--components/test2/test2.wxml-->
<text>components/test2/test2.wxml</text>
<view class="rgb" style="background-color: rgb({{ fullColor}});">
<text>颜色值:{{fullColor}}</text>
</view>
<button size="mini" type="default" bindtap="changeR">R</button>
<button size="mini" type="primary" bindtap="changeG">G</button>
<button size="mini" type="warn" bindtap="changeB">B</button>
<view>{{rgb.r}},{{rgb.g}},{{rgb.b}}</view>
test2.js
// components/test2/test2.js
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
rgb: {
r: 0,
g: 0,
b: 0,
},
fullColor: '0, 0, 0' //根据rgb对象的三个属性,动态计算fullColor的值
},
/**
* 组件的方法列表
*/
methods: {
changeR() {
this.setData({
'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5
})
},
changeG() {
this.setData({
'rgb.g': this.data.rgb.g + 5 > 255 ? 255 : this.data.rgb.g + 5
})
},
changeB() {
this.setData({
'rgb.b': this.data.rgb.b + 5 > 255 ? 255 : this.data.rgb.b + 5
})
},
},
observers: {
// 'rgb.r, rgb.g, rgb.b': function(r, g, b) {
// this.setData({
// fullColor: `${r}, ${g}, ${b}`
// })
// }
'rgb.**': function(obj) {
this.setData({
fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
})
}
}
})
test2.wxss
/* components/test2/test2.wxss */
.rgb {
height: 300rpx;
line-height: 300rpx;
font-size: 36rpx;
color: white;
text-shadow: 0rpx 0rpx 2rpx black;
text-align: center;
}
只在业务逻辑中使用,页面渲染中不使用
好处:可以提升页面更新的性能
改造上面 的案例
// components/test2/test2.js
Component({
options: {
pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
},
/**
* 组件的初始数据
*/
data: {
_rgb: {
r: 0,
g: 0,
b: 0,
},
fullColor: '0, 0, 0' //根据rgb对象的三个属性,动态计算fullColor的值
},
/**
* 组件的方法列表
*/
methods: {
changeR() {
this.setData({
'_rgb.r': this.data._rgb.r + 5 > 255 ? 255 : this.data._rgb.r + 5
})
},
changeG() {
this.setData({
'_rgb.g': this.data._rgb.g + 5 > 255 ? 255 : this.data._rgb.g + 5
})
},
changeB() {
this.setData({
'_rgb.b': this.data._rgb.b + 5 > 255 ? 255 : this.data._rgb.b + 5
})
},
},
observers: {
// '_rgb.r, _rgb.g, _rgb.b': function(r, g, b) {
// this.setData({
// fullColor: `${r}, ${g}, ${b}`
// })
// }
'_rgb.**': function(obj) {
this.setData({
fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
})
}
}
})
lifetimes: {
created() {
console.log('created')
},
attached() {
console.log('attached')
}
}
pageLifetimes: {
show: function() {
// 页面被展示
console.log('show')
},
hide: function() {
// 页面被隐藏
console.log('hide')
},
resize: function(size) {
// 页面尺寸变化
}
}
methods: {
// 生成随机RGB颜色的方法,非事件处理函数建议以_开头
_randomColor() {
this.setData({
_rgb: {
r: Math.floor(Math.random() * 256),
g: Math.floor(Math.random() * 256),
b: Math.floor(Math.random() * 256)
}
})
},
},
pageLifetimes: {
show: function() {
// 页面被展示
// console.log('show')
this._randomColor()
}
}
有3种方式:
this.selectComponent()
获取子组件实例对象 属性绑定
属性绑定用于实现父向子传值,而且只能传递普通类型的数据,无法将方法传递给子组件。父组件的示例代码如下:
//父组件的data节点
data: {
count: 0
}
//父组件的wxml结构
<my-test3 count="{{count}}"></my-test3>
<view></view>
<view>父组件中,count值为:{{count}} </span>
子组件在properties
节点种声明对应的属性并使用。示例代码如下:
//子组件的properties节点
properties: {
count: Number
}
//子组件的wxml结构
<text>子组件中,count值为:{{count}}</text>
事件绑定
事件绑定用于实现子向父传值,可以传递任何类型的值。
使用步骤如下:
this.triggerEvent('自定义事件名称', {/* 参数对象*/})
,将数据发送到子组件e.detail
获取到子组件传递过来的数据步骤1
// 在父组件中定义syncCount方法
// 将来,这个方法会被传递给子组件,供子组件进行调用
syncCount() {
console.log('syncCouont')
}
步骤2
<!-- 使用bind:自定义事件名称 (推荐 结构清晰) -->
<my-test3 count="{{count}}" bind:sync="syncCouont"></my-test3>
<!-- 或在bind后面直接写上自定义事件名称 -->
<my-test3 count="{{count}}" bindsync="syncCount"></my-test3>
步骤3
// 子组件的wxml结构
<text> 子组件中,count的值为: {{count}} </text>
<button type="primary" bindtap="addCount"> + 1 </button>
// 子组件的js代码
methods: {
addCount() {
this.setData({
count: this.properties.count + 1
})
}
//触发自定义事件 将数值同步给父组件
this.triggerEvent('sync', {value: this.properties.count})
}
步骤4
syncCount(e) {
this.setData({
count: e.detail.value
})
}
获取组件实例
可以在父组件里调用this.selectComponent("id或者class选择器")
,获取子组件实例对象,从而直接访问子组件的任意数据和方法。
调用时需要传入一个选择器,例如this.selectComponent(".my-component")
// wxml结构
<my-test3 count="{{count}}" bind:sync="syncCount" class="customA" id="cA"> </my-test3>
<button bindtap="getChild"> 获取子组件实例</button>
getChild() { //按钮的tap事件处理函数
const child = this.selectComponent('.customA)
child.setData({count: child.properties.count+1}) //调用子组件的setData方法
child.addCount() //调用子组件的addCount方法
创建behaviors
根目录下创建behaviors/my-behaviors.js
导入并使用behaviors
// my-component.js
var myBehavior = require('../../behaviors/my-behavior')
Component({
behaviors: [myBehavior],
})
组件和它引用的behaviors
中可以包含同名的字段,此时可以参考如下3种同名时的处理规则:
目前,小程序中已经支持使用npm安装第三方包,从而来提高小程序的开发效率。但是,在小程序中使用npm包有如下3个限制:
Vant Weapp是有赞前端团队开源的一套小程序UI组件库,助力开发者快速搭建小程序应用。它所使用的是MIT开源许可协议。类似于Vue中使用的elementUI
官方文档
npm init -y
生成package.json
文件
npm i @vant/weapp@1.10.3 -S --production
在app.wxss
中,写入css变量,即可对全局生效
page{
/* 定制警告按钮的背景颜色和边框颜色 */
--button-danger-background-color: #C00000;
--button-danger-border-color: #D60000;
}
默认情况下,小程序官方提供的异步API都是基于回调函数实现的,例如,网络请求的API需要按照如下的方式调用:
wx.request({
url: 'example.php', //仅为示例,并非真实的接口地址
data: {
x: '',
y: ''
},
header: {
'content-type': 'application/json' // 默认值
},
success (res) {
console.log(res.data)
}
})
缺点:容易造成回调地狱的问题,代码的可读性、维护性差。
API Promise化,指的是通过额外的配置,将官方提供的、基于回调函数的异步API,升级改造为基于Promise的异步API,从而提高代码的可读性、维护性,避免回调地狱的问题。
在小程序中,实现API Promise化主要依赖于miniprogram-api-promise
这个第三方的npm包。
它的安装和使用步骤如下:
npm install --save miniprogram-api-promise@1.0.4
安装后再次通过工具-构建npm
// 在小程序入口文件app.js中,只需调用一次promisifyAll()方法
// 即可实现异步API的Promise化
import {promisifyAll} from 'miniprogram-api-promise'
const wxp = wx.p = {}
promisifyAll(wx, wxp)
// 页面的wxml结构
<van-button type="danger" bindtap="getInfo"> vant按钮 </van-button>
// 页面的js文件中,定义对应的tap事件处理函数
async getInfo() {
const { data: res } = await wx.p.request({
method: 'GET',
url: 'https://www.escook.cn/api/get',
data: {name: 'zs', age: 20}
})
console.log(res)
}
全局数据共享(又叫做:状态管理)是为了解决组件之间数据共享的问题
开发中常用的全局共享方案有Vuex、Redux、MobX等
在小程序中,可使用mobx-miniprogram
配合mobx-miniprogram-bindings
实现全局数据共享。
其中:
mobx-miniprogram
用来创建Store实例对象
mobx-miniprogram-bindings
用来把Store中的共享数据或方法,绑定到组件或页面中使用。
安装MobX相关的包
npm install --save mobx-miniprogram@4.13.2 mobx-miniprogram-bindings@1.2.1
安装后记得重新构建npm
根目录下创建store文件夹
store/store.js
// 在这个JS 文件中,专门来创建Store的实例对象
import {observable} from 'mobx-miniprogram'
export const store = observable({
num1: 1,
num2: 2
})