app.json定义了小程序的整体结构:
sitemapLocation:暴露至外部搜索的相关配置项。
组件
容器组件样式
几个重要的容器组件:view、scroll-view、swiper。后两者相似,但有一定区别。
view
view类似于div,开辟一个元素容器;
scroll-view
可滚动视图区域。一般是固定区域内,然后将图片、列表等超过尺寸的内容放进去,从而实现滚动。常用参数如下:
scroll-x | true:为允许横向滚动,默认为false | |
scroll-y | true:为允许纵向滚动,默认为false | |
scroll-top | 竖向滚动条位置,number/string类型 | |
scroll-left | 横向滚动条位置,number/string类型 |
比如:
.tabscroll {
height: 40px;
width: 100%;
white-space: nowrap;
.tabsview {
display: inline-block;
padding: 12px 6px;
}
}
其中white-space属性用来处理元素中的空白,有几种选项:normal、nowrap、pre、pre-wrap、pre-line、break-spaces。一般scroll-view与white-space合用,此处选择nowrap表示不对超过一行的数据进行换行,如果选择normal则会换行,滚动失效。
swiper
元素组件
事件绑定
事件包括:点击tap、输入input、长按longtap、触摸开始touchstart、触摸结束touchend、取消触摸touchcancel(表示触摸操作被打断(来电等))。
事件绑定(不携带参数)
在button组件上分别绑定count+1和price+1事件。
//wxml
<view>{{product.count*product.price}}</view>
<button type="primary" bind:tap="addCount">count+1</button>
<button type="primary" bind:tap="addPrice">price+1</button>//定义数据
//ts
Page({
data: {
product:{
price:12,
count:1,
}
},
addCount(){
this.setData(
{
'product.count':this.data.product.count+1
}
)
},
addPrice(){
this.setData(
{
'product.price':this.data.product.price+1
}
)
}
})
阻止冒泡的点击事件绑定, 将bind:tap修改为catch:tap即可。冒泡事件主要就是点击、触摸操作;输入操作一般是非冒泡事件。
互斥事件的绑定,将上述bind:tap修改为mut-bind:tap即可。
事件绑定传参
在html的事件绑定时,不能同时绑定事件处理函数的同时,还指定参数。具体理解看下面这个例子:点击button后,HTML传递一个增量参数,ts接收后更新相应变量值。正确做法如下:
<button type="primary" bind:tap="addNum2" data-add="5">点击count+5</button>
addNum2(e:any){
const add = parseInt(e.target.dataset.add)
this.setData({
'products.count':this.data.products.count+add,
})
},
关键有两点:一是wxml中的参数格式为:data-参数名="{{参数值}}";二是ts文件中,传入参数为e,表示event事件,可以log一下看看具体格式,如下所示:
{type: "tap", timeStamp: 40763481, target: {…}, currentTarget: {…}, mark: {…}, …}
changedTouches: [{…}]
currentTarget: {id: "", offsetLeft: 114, offsetTop: 374, dataset: {…}}
detail: {x: 219.6000213623047, y: 401.550048828125}
mark: {}
mut: false
target:
dataset: {add: "5"}
id: ""
offsetLeft: 114
offsetTop: 374
__proto__: Object
timeStamp: 40763481
touches: [{…}]
type: "tap"
_userTap: true
__proto__: Object
可以看到传递过来的形参add其实就在target.dataset里面,因此提取出来即可。最后使用setData方法给ts中的相关变量赋值即可。
注意:传参时,wxml中的驼峰参数名会被转换为全小写名。
事件的双向绑定:
双向绑定是指,HTML展示页面的内容 与 ts文件中变量的值会双向影响,而不是单向的。一般应用在input、form等组件中。使用范例如下:
<view>
<input class="number-info" type="number" model:value="{{products.count}}" bindinput="ediCount"/>
</view>
ediCount(e:any){
// console.log(e);
const count = parseInt(e.detail.value);
this.setData({
'products.count':count,
})
},
关键:model:value,{{}}中填写要绑定的变量名即可。一次只能绑一个。
事件冒泡问题的处理(补充)
条件渲染
条件渲染就是根据不同的条件渲染不同的页面,一般有两种思路:①通过 IF 条件进行判断;②通过hidden进行隐藏。方式①不会渲染;方式②渲染后再隐藏。
IF条件判断
使用wx:if标签,注意格式。
<view wx:if="{{products.price*products.count<200}}">总价小于200</view>
<view wx:elif="{{products.price*products.count>=200&&products.price*products.count<2000}}">总价小于2000</view>
<view wx:else="{{products.price*products.count>=2000}}">总价大于2000</view>
hidden
注意条件为true的逻辑。
<view hidden="{{!(products.price*products.count<200)}}">总价小于200</view>
<view hidden="{{!(products.price*products.count>=200&&products.price*products.count<2000)}}">总价小于2000</view>
<view hidden="{{products.price*products.count<=2000}}">总价大于2000</view>
列表渲染
列表渲染主要关注 index和item即可。使用 wx:for-item
可以指定数组当前元素的变量名,使用 wx:for-index
可以指定数组当前下标的变量名。
commodity:[
{
name:'apple',
price:5
},
{
name:'banana',
price:3
},
{
name:'orange',
price:2
},
]
<view>
<block wx:for="{{commodity}}">
<text>第{{index+1}}个商品名:{{item.name}},价格:{{item.price}}\n</text>
</block>
</view>
。
异步编程-使用async+await
使用
promise
封装wx.request
请求使用
async
和await
简化promise
的操作
微信小程序支持Promise,可以结合async+await,完成异步编程。以下案例中,将wx.request封装至Promise对象中,然后通过async+await进行调用,完成异步操作。
①html在button按钮上绑定事件:
<view>
<button type="default" bind:tap="onAsyncMethod">点击执行async异步方法</button>
</view>
②创建promise对象,对象包含实际业务操作,即包裹了wx.request请求的相关操作。
pA(){
return new Promise((resolve,reject)=>{
console.log('执行A接口的逻辑');
wx.request({
url:'http://127.0.0.1:8081/allAddress',
method:'GET',
responseType:'text',
success:(res) => {
resolve(res)
},
fail:(err)=>{
reject(err)
}
})
})
},
③创建HTML中设置的事件处理函数,并使用async+await的方法调用上述promise对象,最后将结果log出来。代码如下:
async onAsyncMethod(){
const res = await this.pA();
console.log(res);
}
使用异步编程完成列表数据的初始化
结合小程序页面的生命周期,在onReady中调用request请求,获取到listData。同样需要结合promise。
getDataList():any{
return new Promise((resolve,reject)=>{
wx.request({
url:'http://127.0.0.1:8081/allAddress',
method:'GET',
responseType:'text',
success:(res)=>{
console.log('request:'+res);
console.log('request.data:'+res.data);
resolve(res.data);
},
fail:(e)=>{
reject(e);
}
})
})
},
onReady:async function(){
console.log('onReady');
const data:string[] = await this.getDataList();
console.log('data为'+data[0]);
this.setData(
{
'this.listOfData':data
}
);
},
对比promise和async/await两种方式
案例的界面如下:上面搜索框为promise,下面搜索框为async/await。
// index.ts
// 获取应用实例
const app = getApp<IAppOption>()
Page({
data: {
responsibilityGroupList1:[],
responsibilityGroupList2:[],
inputVal1:'',
inputVal2:'',
},
onLoad() {
this.getData('').then((result:any)=>{
console.log(result);
this.setData({
'responsibilityGroupList1':result.data,
'responsibilityGroupList2':result.data,
})
})
},
getData(groupName:any){
return new Promise((resolve,reject)=>{
wx.request({
url:'http://localhost:8081/fuzzyResponsibilityGroup',
data:{
groupName:groupName
},
method:'GET',
header: {
'content-type': 'application/json' // 默认值
},
success(res:any){
if(res.statusCode === 200){
resolve(res);
}else{
reject(res);
}
},
fail(e:any){
reject(e);
}
})
})
},
search1(){
this.getData(this.data.inputVal1).then((result:any)=>{
console.log(result);
this.setData({
'responsibilityGroupList1':result.data
})
}) },
async search2(){
let result :any= await this.getData(this.data.inputVal2)
this.setData(
{
'responsibilityGroupList2':result.data
}
)
}
})
<text>使用promise请求</text>
<view class="serachview">
<label for="searchinput">用户名称:</label>
<input id="searchinput" type="text" placeholder="请输入名称" model:value="{{inputVal1}}"/>
<button size="mini" type="primary" bind:tap="search1">搜索</button>
</view>
<text>\n</text>
<block wx:for="{{responsibilityGroupList1}}">
<view class="listBlock">item.groupName is :{{item.groupName}} , projectId is : {{item.projectId}}</view>
</block>
<text>\n使用async/await请求</text>
<view class="serachview">
<label for="searchinput">用户名称:</label>
<input id="searchinput" type="text" placeholder="请输入名称" model:value="{{inputVal2}}"/>
<button size="mini" type="primary" bind:tap="search2">搜索</button>
</view>
<text>\n</text>
<block wx:for="{{responsibilityGroupList2}}">
<view class="listBlock">item.groupName is :{{item.groupName}} , projectId is : {{item.projectId}}</view>
</block>
说明:使用async时,search2函数需要用async包裹,调用的获取方法加await前缀,表示等待结果的获取。
生命周期
页面的生命周期
此处指小程序页面的生命周期,主要包含以下五个阶段:onLoad(初次加载时的渲染)、onReady(初次渲染完成后)、onShow(返回页面时)、onHide(离开页面时)、onUnload(卸载销毁页面时)。
官网上对页面生命周期的描述如下:包含视图层和逻辑层。
// pages/list/list.js
Page({
...
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
console.log('onLoad');
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
console.log('onReady');
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
console.log('onShow');
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
console.log('onHide');
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
console.log('onUnload');
},
...
})
onLoad和onReady的区别:onLoad是在小程序初次渲染时执行;onReady比onLoad晚,是在渲染结束后执行,能够操作DOM元素,一般用来加载数据。
组件的生命周期
组件生命周期包含:created、attached、ready、moved、detatched、error。最重要常用的是created、attached、detatched。
路由跳转
路由跳转主要依赖navigate,实现方式主要分为声明式路由跳转和编程式路由跳转。针对不同场景,学习了跳转至非tabBar、tabBar、以及返回,携带参数等情况下的路由跳转。
主要有5个API提供导航跳转和调回的功能:navigateTo、navigateBack、redirectTo、switchTab、reLaunch。
API | 作用 |
navigateTo | 不关闭当前页面,路由至下一页面;可以通过navigateBack返回至前一页面。仅适用于非tabBar页面 |
navigateBack | 与navigateTo相匹配,导航返回至原页面 |
redirectTo | 当前页面出栈,路由至下一个页面,仅适用于非tabBar页面 |
switchTab | 全部页面出栈,路由至新tabBar页面,关闭其他所有非 tabBar 页面,仅适用于tabBar页面 |
reLaunch | 页面全部出栈,打开新的页面,适用于任意页面 |
具体使用可以分为声明式路由和编程式路由,均在以下的学习场景中给出。
学习场景如下:
已有两个tabBar页面:logs、list。list中的内容能点击跳转至详情页面,详情页面有返回的点击按钮。
声明式路由
声明式路由是指采用wxml标签的方式,wxml标签形式如下:
<navigator url="/pages/details/details" open-type="navigateTo">navigateTo跳转至detail页面</navigator>
<navigator url="/pages/details/details" open-type="redirectTo">redirectTo跳转至detail页面</navigator>
<navigator url="/pages/details/details" open-type="reLaunch">reLaunch跳转至detail页面</navigator>
navigator标签较为常用,渲染为文字,注意navigator标签不能与button嵌套,可以与text嵌套。常用参数如下:target(跳转后的目标小程序)、url(目标路径,开头需加斜杠"/")、open-type(跳转方式:navigate、redirect、swithTab等),点击查看全部参数信息。
navigator标签的常用属性 | 说明 |
target | 在哪个目标上发生跳转,默认当前小程序 |
url | 目标路径,携带参数采用requestParam的形式 |
open-type | 跳转方式,包括:navigate、redirect、switchTab、reLaunch、navigateBack、exit。 |
案例如下,包含携带参数和不携带参数的情况。
携带参数时,根据参数类型分为几种情况,单参数、多参数、对象类型。参数携带方法基本一致,不同之处在于,对象类型的应先转换为json字符串,接收后再进行解析。
不带参数时,通用的声明式路由为:
<navigator url="/pages/details/details" open-type="navigate">不携带参数navigateTo跳转至非tabSet的detail页面</navigator>
携带普通单参数及多参数时,通用的声明式路由为:
<navigator url="/pages/details/details?value={{passValue}}" open-type="navigate">携带单参数navigateTo跳转至非tabSet的detail页面</navigator>
对于对象参数,因json字符串序列化的缘故,应选择编程式路由进行跳转。
跳转至非tabBar
从log页面跳转至detail页,使用navigate标签,分别展示了六种不同情况,最后一种携带对象参数情形中,若不对对象参数进行json序列化,则会输出[object,object]。
<!-- 三种方式实现不携带参数的路由跳转 -->
<navigator url="/pages/details/details" open-type="navigate">不携带参数navigateTo跳转至非tabSet的detail页面</navigator>
<navigator url="/pages/details/details" open-type="redirect">不携带参数redirectTo跳转至非tabSet的detail页面</navigator>
<navigator url="/pages/details/details" open-type="reLaunch">不携带参数reLaunch跳转至非tabSet的detail页面</navigator>
<!-- 三种方式实现携带参数的路由跳转 -->
<view style="color: orange;">
<navigator url="/pages/details/details?value={{passValue}}" open-type="navigate">携带<text style="color: red;">单参数navigateTo</text>跳转至非tabSet的detail页面</navigator>
<navigator url="/pages/details/details?value={{passValue}}&type=redirect" open-type="redirect">携带<text style="color: red;">多参数redirectTo</text>跳转至非tabSet的detail页面</navigator>
<navigator url="/pages/details/details?value={{product}}" open-type="reLaunch">携带<text style="color: red;">对象参数reLaunch</text>跳转至非tabSet的detail页面</navigator>
</view>
后三种情形的detail-ts页面如下:
onLoad (options) {
console.log(options)
let navigateType = options.type;
if(navigateType === 'redirect'){
console.log(options.value)
this.setData({
'redirectText' : options.value,
})
}
},
。
跳转回原页面
在跳转至非tabBar页面后,如果需要返回至原页面,仍使用navigate组件,组件内需要补充属性:open-type="navigateBack"。
<button type="default">
<navigator open-type="navigateBack">
<text>点击返回list页面</text>
</navigator>
</button>
跳转至tabBar页面
若要跳转至tabBar页面,将open-type修改为switchTab即可:
<!--声明式tabBar页面跳转测试-->
<button>
<navigator open-type="switchTab" url="/pages/logs/logs">点击跳转至tabBar页面logs</navigator>
</button>
编程式路由
开发文档提供了一系列接口,如switchTab、navigateTo、navigateBack、redirectTo,用来实现页面的路由跳转功能。
跳转至非tabBar页面
保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。以下案例中,通过监听button的点击事件完成跳转,代码如下:
使用编程式,跳转前的wxml文件:
<!-- 编程式:三种方式实现不携带参数的路由跳转 -->
<button size="mini" type="default" style="width: 33%;font-size: 21rpx;line-height: 35rpx;" bind:tap="navigateToTest">无参数编程式navigateTo路由跳转</button>
<button size="mini" type="default" style="width: 33%;font-size: 21rpx;line-height: 35rpx;" bind:tap="redirectToTest">无参数编程式redirectTo路由跳转</button>
<button size="mini" type="default" style="width: 33%;font-size: 21rpx;line-height: 35rpx;" bind:tap="reLaunchTest">无参数编程式reLaunch路由跳转</button>
<!-- 编程式:三种方式实现携带参数的路由跳转 -->
<button size="mini" type="default" id="paramNavigateToTest111" style="width: 33%;font-size: 21rpx;line-height: 35rpx;" bind:tap="paramNavigateToTest">携带参数编程式navigateTo路由跳转</button>
<button size="mini" type="default" style="width: 33%;font-size: 21rpx;line-height: 35rpx;" bind:tap="paramRedirectToTest">携带参数编程式redirectTo路由跳转</button>
<button size="mini" type="default" style="width: 33%;font-size: 21rpx;line-height: 35rpx;" bind:tap="paramReLaunchTest">携带参数编程式reLaunch路由跳转</button>
使用编程式,跳转前的ts文件:包含了单参数、多参数、对象参数,对象参数需要序列化。
navigateToTest(){
wx.navigateTo(
{
url:'/pages/details/details'
}
)
},
redirectToTest(){
wx.redirectTo(
{
url:'/pages/details/details'
}
)
},
reLaunchTest(){
wx.reLaunch(
{
url:'/pages/details/details'
}
)
},
paramNavigateToTest(e:any){
console.log(e)
wx.navigateTo(
{
url:'/pages/details/details?value='+this.data.passValue
}
)
},
paramRedirectToTest(){
wx.redirectTo(
{
url:'/pages/details/details?value='+this.data.passValue+'&type=redirect'
}
)
},
paramReLaunchTest(){
let productJson = JSON.stringify(this.data.product);
wx.reLaunch(
{
url:'/pages/details/details?value='+productJson
}
)
},
使用编程式,跳转后detail页面的ts文件:
onLoad (options:any) {
let product = JSON.parse(options.value)
console.log(product)
let navigateType = options.type;
if(navigateType === 'redirect'){
console.log(options.value)
this.setData({
'redirectText' : options.value,
})
}
}
在上述跳转后detail的ts代码中,在onLoad初始化时处理跳转请求。这部分代码与声明式的没有区别,注意对象传参的格式:options.value,这里的value与路径中的参数名无关。
跳转至tabBar页面
跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。使用switchTab,这与跳转至非setTab页面格式一致。
组件
组件与pages相对应,一般来说,将组件可以复用的部分独立出来,如tabs、list等。组件中建议使用class选择器。
基础组件的创建
组件的创建包含创建和使用两部分,首先创建组件tabs,要在mine中使用组件tabs,则需要定义(类似于angular的<out-let>标签的作用)。如下:
{
"usingComponents": {
"tabs":"/components/tabs/tabs",
"list":"/components/list/list"
}
<view>
<tabs></tabs>\n
<list></list>
</view>
上述案例中,要复用的组件为tabs组件,其内容如下:
// components/tabs/tabs.ts
Component({
/**
* 组件的属性列表
*/
properties: {
},
/**
* 组件的初始数据
*/
data: {
tabList: [],
active:-1
},
/**
* 组件的方法列表
*/
methods: {
getTabList() {
wx.request(
{
url: "http://localhost:8081/fuzzyResponsibilityGroup",
method: "GET",
header: {
'content-type': 'application/json' // 默认值
},
success: (res: any) => {
if (res.statusCode === 200) {
this.setData({
'tabList': res.data,
active:0
})
console.log(this.data.tabList)
}
}
}
)
}
},
/* 生命周期created attached detached */
lifetimes: {
created() {
this.getTabList();
}
}
})
<!--components/tabs/tabs.wxml-->
<scroll-view class="tabscroll" scroll-x>
<view wx:for="{{tabList}}" wx:key="index" class="tabsview {{ active === index ? 'active' : '' }}">{{item.groupName}}</view>
</scroll-view>
/* components/tabs/tabs.wxss */
.tabscroll {
// height: 40px;
width: 100%;
white-space: nowrap;
.tabsview {
display: inline-block;
padding: 12px 6px;
}
}
.active {
color: #f94d2a;
}
上述tabs页面结果如下:
ts文件包含了component构造器,包含properties、data、methods、lifetimes(包含create、attach、depatch)。
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
// 一般用来指定父组件传递过来的参数。
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
},
/* 生命周期created attached detached */
lifetimes: {
created() {
this.getTabList();
}
},
//数据监听器,用于监听本页面数据,采用key-function的形式,function中可以赋新值,也可以setdata
observers:{
"key":function(param){
// new value function
}
}
})
组件生命周期
上述component构造器中,重点为生命周期,包括三个阶段,create、attached、depatched。
- 组件实例刚刚被创建好时,
created
生命周期被触发。此时,组件数据this.data
就是在Component
构造器中定义的数据data
。 此时还不能调用setData
。 通常情况下,这个生命周期只应该用于给组件this
添加一些自定义属性字段。 - 在组件完全初始化完毕、进入页面节点树后,
attached
生命周期被触发。此时,this.data
已被初始化为组件的当前值。这个生命周期很有用,绝大多数初始化工作可以在这个时机进行。 - 在组件离开页面节点树后,
detached
生命周期被触发。退出一个页面时,如果组件还在页面节点树中,则detached
会被触发。
数据监听器
数据监听器用来监听本页面或者子页面数据或者属性的变化。例如, this.data.sum
是this.data.numberA
与 this.data.numberB
的和。此时,可以使用数据监听器进行如下实现。
Component({
attached: function() {
this.setData({
numberA: 1,
numberB: 2,
})
},
observers: {
'numberA, numberB': function(numberA, numberB) {
// 在 numberA 或者 numberB 被设置时,执行这个函数
this.setData({
sum: numberA + numberB
})
}
}
})
上述例子中,监听了numberA 和numberB ,当其变化时,两数之和也会变化。
组件间通信与事件
包含父组件向子组件通信、子组件向父组件通信、父组件还能通过获取子组件实例对象来进行通信、兄弟组件之间的通信需要借助同一个父组件。
父向子传递
父向子传递参数需要借助子组件中的properties。下例中,从父组件传递了tabSelectId给子组件的tabId。注意,父组件中以子组件的属性名为key,以父组件的属性名为value;此外,在子组件中定义接收参数时,指定的类型需要为包装类型。
// 父组件:通过自定义属性的形式传递数据,以子组件中定义的 key 为属性名,以要传递的数据为属性值
<list tabId="{{tabSelectId}}">,
// 子组件:通过 properties 声明要从父组件中接收的数据
/**
* 组件的属性列表
*/
properties: {
tabId: String
},
子向父传递
子向父传递参数需要借助triggerEvent。triggerEvent是component自带的触发事件,包含两个参数:name、param。子组件通过triggerEvent发出后,父组件需要在wxml中接收该事件,并指定处理函数。
子组件tabs的ts:
observers:{
active:function(active){
const {id} = this.data.tabList[active];
this.setData({
'selectedId':id
}),
this.triggerEvent('indexChangeEvent',{id})
}
},
父组件的wxml:
<tabs value="{{tempVal}}" bind:indexChangeEvent="tabsIndexChange"></tabs>\n
父组件的ts:
tabsIndexChange(event:any){
console.log("tabsIndexChange is :",event.detail)
},
父获取子的实例
// 父组件
Page({
data: {},
getChildComponent: function () {
const child = this.selectComponent('.my-component');
console.log(child)
}
})
兄弟组件之间的传递
兄弟组件之间的传递,需要借助共同父组件;即:子组件tabs向父组件mine传递,然后父组件mine再向子组件list传递。
tabs子组件如下:
observers:{
active:function(active){
const {id} = this.data.tabList[active];
this.setData({
'selectedId':id
}),
this.triggerEvent('indexChangeEvent',{id})
}
},
mine父组件的接收如下:
<tabs bind:indexChangeEvent="tabsIndexChange"></tabs>\n
mine父组件的ts文件如下:
tabsIndexChange(event:any){
console.log("tabsIndexChange is :",event.detail)
this.setData({
selectedId:event.detail.id
})
},
至此,子组件tabs向父组件mine传递selectedId完毕。然后需要将该值从父组件传递至子组件。
mine父组件的ts文件如下:
<list selectedId="{{selectedId}}"></list>
list子组件的ts文件如下:
properties: {
selectedId:Number
},
methods: {
getDetailList(name: string) {
wx.request({
url: "http://localhost:8081/fuzzyResponsibilityGroup",
method: "GET",
data: { groupName: name },
header: {
'content-type': 'application/json' // 默认值
},
success: (res: any) => {
console.log(res)
this.setData({
detailList: res.data
})
}
})
}
},
//监听selectedId的变化,并进行请求。
observers:{
//监听selectedId的变化并调用详情列表
selectedId:function(selectedId: any){
console.log('list selectId is ', selectedId)
this.getDetailList(selectedId)
}
}
list子组件的wxml文件如下:
<view wx:for="{{detailList}}" wx:key="item">{{item.groupName}}</view>
最后结果如下:
组件插槽slot
一个子组件可以由多个父组件复用,当父组件需要展示不同的内容时,就需要用到插槽。下例展示了多插槽的用法,用name进行区分。·
在子组件list文件中:
<!--components/list/list.wxml-->
<slot name="header"></slot>
<view wx:for="{{detailList}}" wx:key="item">list详细列表为{{item.groupName}}</view>
<slot name="footer"></slot>
options:{
multipleSlots:true
},
mine文件中:
<list selectedId="{{selectedId}}">
<view slot="header" class="slot">头部插槽</view>
<view slot="footer" class="slot">尾部插槽</view>
</list>