微信小程序

 app.json定义了小程序的整体结构:

sitemapLocation:暴露至外部搜索的相关配置项。

组件

容器组件样式

几个重要的容器组件:view、scroll-view、swiper。后两者相似,但有一定区别。

view

view类似于div,开辟一个元素容器;

scroll-view

可滚动视图区域。一般是固定区域内,然后将图片、列表等超过尺寸的内容放进去,从而实现滚动。常用参数如下:

scroll-xtrue:为允许横向滚动,默认为false
scroll-ytrue:为允许纵向滚动,默认为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

  1. 使用 promise 封装 wx.request 请求

  2. 使用 asyncawait 简化 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>

WXS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值