美文网首页微信
微信小程序

微信小程序

作者: sweetBoy_9126 | 来源:发表于2020-12-12 16:40 被阅读0次

    1. 组件通信

    1.1. 父子组件通信

    • 父传子
      子组件通过properties接受这个属性,这个属性会被放到子组件的data里,可以使用this.data.attrname拿到这个属性值
      parent.xml
    <view>
      <child test="aaa"></child>
    </view>
    

    child.js

    Component({
      properties: {
        test: {
          type: String,
          value: ''
        }
      }
    })
    
    • 子传父
      子组件通过triggerEvent触发父组件自定义事件,在使用这个组件的时候在组件标签上监听这个事件
      parent.xml
    <view>
      <child bind:myEvent="handleEvent"/>
    </view>
    

    child.js

    methods: {
      onClickTest(data) {
        this.triggerEvent('myEvent', data)
      }
    }
    
    • 兄弟组件通信
      1). globalData
      将数据挂载到 app.js,这种方式在开发中很常用。通过getApp(),我们能够在任何一个页面内访问到app实例。
      app.js
    App({
      globalData:{
        list:[]
      }
    })
    

    page1.js

    const app = getApp()
    Page({
      onLoad(){
        app.globalData.list.push({
          id: 10
        })
      }
    })
    

    page2.js

    const app = getApp()
    Page({
      onLoad(){
        console.log(app.globalData.list) // [{id:10}]
      }
    })
    

    2). storage
    storage并不是作为通信的主要方式。storage 主要是为了缓存数据,并且最多只能存储10M的数据,我们应该合理使用storage

    wx.setStorageSync('timestamp', Date.now())
    wx.getStorageSync('timestamp')
    wx.removeStorageSync('timestamp')
    

    3). eventBus

    class EventBus {
        constructor() {
            this.cacheData= {}
        }
        on(eventName, fn) {
            this.cacheData[eventName] = this.cacheData[eventName] || []
            this.cacheData[eventName].push(fn)
        }
        emit(eventName, data) {
            this.cacheData[eventName] = this.cacheData[eventName] || []
            this.cacheData[eventName].forEach((fn) => fn(data))
        }
        off(eventName, fn) {
            if (this.cacheData[eventName]) {
                const currentIndex = this.findIndex(eventName, fn)
                this.cacheData[eventName].splice(currentIndex, 1)
            } 
        }
        findIndex(eventName, fn) {
            for (let i = 0; i < this.cacheData[eventName].length; i++) {
                if (fn === this.cacheData[eventName][i]) {
                    return i
                }
            }
        }
    }
    export default new EventBus()
    

    page1.js

    import eventBus from '@Utils/eventBus'
    ready() {
            eventBus.on('update:addSelected', this.handleUpdateAddSelected.bind(this))
            eventBus.on('update:removeSelected', this.handleUpdateRemoveSelected.bind(this))
        },
    

    page2.js

    import eventBus from '@Utils/eventBus'
    methods: {
      handleUpdateSelect() {
                if(this.data.active) {
                    console.log(4)
                    eventBus.emit('update:removeSelected', this.data.name)
                } else {
                    console.log(5)
                    eventBus.emit('update:addSelected', this.data.name)
                }
            }
    }
    

    2. 获取组件实例

    可在父组件里调用 this.selectComponent ,获取子组件的实例对象。(插件的自定义组件将返回 null),调用时需要传入一个匹配选择器 selector,如:this.selectComponent(".my-component"),类似于vue的ref

    // 父组件
    Page({
      data: {},
      getChildComponent: function () {
        const child = this.selectComponent('.my-component');
        console.log(child)
      }
    })
    

    3.生命周期

    created相当于vue的beforeCreated
    attached相当于vue的created
    ready相当于vue的mounted
    detached相当于vue的beforeDestory

    4. behaviors

    相当于vue的mixin,会在使用的时候把里面的数据和当前实例合并
    单独的behaviors.js文件写法

    module.exports = Behavior({
      data: {},
      ...
    })
    

    observers数据监听(类似于vue的watch)

    Component({
      attached: function() {
        this.setData({
          numberA: 1,
          numberB: 2,
        })
      },
      observers: {
        'numberA, numberB': function(numberA, numberB) {
          // 在 numberA 或者 numberB 被设置时,执行这个函数
          this.setData({
            sum: numberA + numberB
          })
        }
      }
    })
    

    4.给事件传递参数

    使用data-属性,注意data-后面跟的必须是全小写的字符

    <view class="network-debug-content-part-content" bindtap="handleRequestDataCopy" data-requestlist="aaa">
    </view>
    
    handleRequestDataCopy(event) {
                console.log(event.currentTarget.dataset.requestlist, 'aaa')
    }
    

    5. 插槽

    用法

    <!-- 在组件的wxml中定义插槽 -->
    
    <view>
    
        <!-- 默认插槽 -->
        <slot></slot>
    
        <!-- 具名插槽 -->
        <slot name="before"></slot>
    
        <slot name="after"></slot>
    
    </view>
    
    
    
    <!-- 在页面组件中使用 -->
    
    
    <dong my-class="add">
    
      <text>默认的插槽</text>
    
      <view slot="after">具名插槽</view>
    
      <view slot="before">具名插槽</view>  
    
    </dong>
    

    默认一个组件只支持一个插槽,如果想要使用多个插槽还需要在组件的js文件里配置options

    Component({
    
    
        options: {
    
            multipleSlots: true
        }
    })
    

    如果想要实现有slot的时候只显示slot里的内容,没有slot的时候显示默认内容,可以使用css3 empty来实现

    <view class="has-next-box has-next-customer">
    
    <slot></slot>
    
    </view>
    
    <view class="has-next-box has-next-default">
    
    没有更多数据
    
    </view>
    
    
    .has-next-customer {
     
     display: none;
    }
    
    
    .has-next-customer:not(:empty) {
      display: block;
    }
    
    
    .has-next-customer:not(:empty)+.has-next-default {
      display: none;
    }
    

    6. 微信小程序阻止触发父组件事件

    将bindtap换成catchtap就可以

    7. 对于key值不固定的对象在xml里遍历后想拿到每一个的key和value的方法

    将一个键值对拆分成两个,将原来的key和value分别作为value
    比如:

    {a: 1},{b:2}
    拆分成
    {key1: a, key2: 1},
    {key1: b, key2: 2}
    

    7.template的使用

    template主要是简化xml代码的,可以搭配behaviors对js重复代码进行复用
    只要我们的xml文件里使用了<template name="模板名">就可以被使用
    1).在当前页面使用
    直接通过<template is="模块名 data={{数据}}">
    2).在其他页面或者组件里使用

    <import src="../network-debug/index.wxml" />
    这里引入的l我们这个文件本身可以使xml文件,但是在import里必须写成wxml
    <template is="模块名 data={{数据}}">
    

    template模板里的方法需要在当前组件或者页面里写,如果很多地方都用到这些方法,我就就需要通过behavior引用这些方法。

    问题:

    1).解决弹窗层内容可拖动会底层内容跟着拖动的问题
    一:给弹窗层组件设置一个catchtouchmove="ture"让它阻止父组件的touchmove;
    这种情况下,我们弹窗层的touch事件也无法触发了
    二:所以我们需要把弹窗层里的内容放到scroll-view组件里,这样它就可以拖动了;
    因为scroll-view组件有回弹,所以如果我们底部有遮罩层的话,它拖动的时候会显示底部遮罩层的内容,所以我们需要给scroll-view标签设置背景色为我们的弹窗展示层的背景色(白色)

    <block>
        <view class="collapse-drawer" w:if="{{visible}}" catchtouchmove="ture">
            <p-mask visible="{{visible}}" bindmasktap="handleHideMask" z-index="{{zIndex}}"/>
            <view class="collapse-drawer-wrapper {{visible ? 'collapse-drawer-wrapper-enter' : ''}}" style="z-index: {{zIndex}}">
                <view class="collapse-drawer-wrapper-header">
                    <slot name="header"/>
                </view>
                <scroll-view scroll-y="true" style="height: {{contentHeight}}" class="collapse-drawer-wrapper-scroll">
                    <slot/>
                </scroll-view>
            </view>
        </view>
    </block>
    .collapse-drawer {
        background: #fff;
        border-radius: 20rpx 20rpx 0 0;
        overflow: hidden;
        &-wrapper {
            position: fixed;
            bottom: 0;
            left: 0;
            width: 100%;
            background: #fff;
            transform: translateY(100%);
            transition: all .3s linear;
            border-radius: 20rpx 20rpx 0 0;
            overflow: hidden;
            &.collapse-drawer-wrapper-enter {
                transform: translateY(0);
            }
            &-scroll {
                background: #fff;
            }
        }
    }
    

    2). 微信小程序的数据更新视图是只有当相关的data都变了视图才会变,如果只有一部分data变了,那么视图不会变
    比如:


    上面的item是data里的一项,它变了但是因为后面的requestItem.key(requestItem是另一个data里的一项)每次都是固定的,所以当前这个text也不会变

    解决办法:对内层的wx:for遍历结构改成template的方式

    相关文章

      网友评论

        本文标题:微信小程序

        本文链接:https://www.haomeiwen.com/subject/jrxygktx.html