微信小程序:自定义组件的数据传递

微信小程序:自定义组件的数据传递

转载链接地址:[https://segmentfault.com/a/1190000014474289?utm_source=index-hottest](https://segmentfault.com/a/1190000014474289?utm_source=index-hottest)

一、前言

如果小程序中有可复用的UI且具有一定的功能性,就可以使用自定义组件将其封装起来。(如果仅仅只需要复用UI可使用template)下面介绍父子组件的数据传递方法,以及一个简单的组件和一个复杂的组件示例。
【由于刚开始写这篇文章的时候我还算是一个小程序的新手,自己看着官方文档研究并整理归纳的,有很多不足以及错误的地方。在经过一年的沉淀以后(虽然这一年我主要在写vue而不是小程序),我决定重新整理这篇浏览量比较大的文章,以免新手因我的文章走了弯路。】

二、父子组件传递数据的方法

1.父组件向子组件传递数据
parent.wxml

<my-component name="{{name}}" age="{{age}}"></my-component>

parent.js

data: {
  name: 'Peggy',
  age: 25
}

child.js

properties: {
  name: {
    type: String,
    value: '小明'
  },
  age: Number
}

父组件向子组件传值以属性的形式,子组件以properties接收,并可指定数据类型type以及默认值value。
在wxml里可直接以{{name}}的形式使用,而在js中以this.properties.name获取。

2.子组件向父组件传值
child.js

methods: {
  changeName() {
    this.triggerEvent('changeName', {
      name: '李四'
    })
  }
}

parent.wxml

<my-component name="{{name}}" age="{{age}}" bindchangeName="changeName"></my-component>

parent.js

changeName(event) {
  console.log(event.detail)
  // { name: '李四' }
}

子组件向父组件传递数据使用this.triggerEvent方法,这个方法接受3个参数:
this.triggerEvent(‘myevent’, myEventDetail, myEventOption);

myevent为方法名,
myEventDetail是传到组件外的数据,
myEventOption为是否冒泡的选项,有三个参数可以设置:

bubbles    默认false 事件是否冒泡
composed 默认false 事件是否可以穿越组件边界
capturePhase 默认false 事件是否拥有捕获阶段

在父组件监听事件bindchangeName=“changeName”,在changeName方法里有一个event参数,可以从event.detail里拿到组件内部传出来的值。

三、简单的组件(计数器)

在这里插入图片描述
1. 组件功能介绍
这个组件常见于外卖软件中,用于记录想要购买的商品的数量。初始化的时候只有一个加号,点击加号以后出现数字和减号,并最后将数字传到组件外供外部使用。

2. 创建组件
首先在根目录创建components文件夹(推荐),然后创建num-controller文件夹(我取的组件名字),在这个文件夹上点击右键新建一个component,名字为index。
在这里插入图片描述
/components/num-controller/index.wxml

<view class="num-controller">
  <image src="images/minus.png" class="{{num <= min ?'hide': ''}}" bindtap="sub"></image>
  <text class="num">{{num}}</text>
  <image src="images/plus.png" bindtap="add"></image>
</view>

这段代码就是加减两个按钮和一个数字。
/components/num-controller/index.json

{
  "component": true,
  "usingComponents": {}
}

这个文件在创建component的时候会自动写入这段代码。
/components/num-controller/index.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    nameId: {
      type: String
    },
    num: {
      type: Number,
      value: 0
    },
    int: {
      type: Number,
      value: 1
    },
    min: {
      type: Number,
      value: 0
    }
  },

  /**
   * 组件的初始数据
   */
  data: {

  },

  /**
   * 组件的方法列表
   */
  methods: {
    numChange() {
      this.triggerEvent('numChange', {
        num: this.properties.num,
        nameId: this.properties.nameId
      })
    },
    add() {
      this.setData({
        num: this.properties.num + this.properties.int
      })
      this.numChange()
    },
    sub() {
      this.setData({
        num: this.properties.num - this.properties.int
      })
      this.numChange()
    }
  }
})

在组件内部我定义了4个属性,properties是父组件传给子组件的属性。
nameId用来标识子组件的唯一性,如果在父组件内有多个计数器,子组件想把改变的数据传给父组件时可以用到;
num代表计数器中的数字,默认为0;
int代表加减一次改变多少,默认为1;
min代表计数器的最小值,等于这个值时减号会消失,默认为0。

同时在子组件内定义了两个方法:
add点击加号触发,首先改变子组件内部的数字,同时触发numChange方法将改变的数字传到组件外部;
sub点击减号触发,首先改变子组件内部的数字,同时触发numChange方法将改变的数字传到组件外部。

3. 引入组件
假如我要在index.wxml里引入组件:

<num-controller nameId="num1" num="{{num1}}" bindnumChange="numChange"></num-controller>
<num-controller nameId="num2" num="{{num2}}" int="{{5}}" min="{{5}}" bindnumChange="numChange"></num-controller>
<num-controller nameId="num3" num="{{num3}}" int="{{100}}" bindnumChange="numChange"></num-controller>

index.json

{
  "usingComponents": {
    "num-controller": "/components/num-controller/num-controller"
  }
}

想在页面中使用组件必须在json文件里注册组件。
index.js

Page({
  data: {
    num1: 0,
    num2: 10,
    num3: 100
  },
  numChange(event) {
    const {num, nameId} = event.detail
    this.setData({
      [nameId]: num
    })
  }
})

data里的num1, num2, num3是从组件外传入的num,在numChange方法里用event.detail可以拿到组件内部通过this.triggerEvent传出来的数据,然后根据业务需求做逻辑修改。

四、复杂的组件(筛选面板)

在这里插入图片描述
这是一个二级菜单,点击左边(一级)会改变右边(二级)的展示。
1. 创建组件并引入
组件内部:
/components/filter-panel/index.wxml

<view class="filter-panel">
  <view class="panel-container">
    <view class="panel-left">
      ...
    </view>

    <view class="panel-right">
      ...
    </view>
  </view>
</view>

/components/filter-panel/index.json

{
  "component": true,
  "usingComponents": {}
}

组件外部:
假如我要在index.wxml里引入组件:

<filter-panel></filter-panel>

这样就成功引入组件啦~(说真的组件化做好了非常舒服,后期会省很多力气)
2.组件与外部的数据传递
(1) 固定数据渲染
组件外部:
index.wxml

<filter-panel list="{{list}}" active="{{active}}"></filter-panel>

index.js

data: {
  list: [
    ['附近', '地铁站'],
    [['不限', '1km', '2km', '3km'], ['江汉路', '积玉桥', '洪山广场', '楚河汉街', '光谷广场']]
  ],
  active: [0, 0]
},

组件内部:

/components/filter-panel/index.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    list: Array,
    active: Array
  },
  /**
   * 组件的方法列表
   */
  methods: {
    ...
  }
})

如果想从组件外向组件内传递数据,直接在外部引用时以属性的方式传入。
这里我传入了2个属性:
list是二级选择面板渲染的数据。
active是用户选择的选项数据。

到这里组件已经可以正常展示了,但是点击显示选中项还未实现。

(2) 可变数据渲染
控制组件active项的是外部的数据active: [0, 0],通过组件以属性的形式传到了内部。

/components/filter-panel/index.wxml

<view class="filter-panel">
  <view class="panel-container">
    <view class="panel-left">
      <ul>
        <li 
          class="{{active[0] == index? 'active': ''}}" 
          wx:for="{{list[0]}}" 
          wx:key="{{index}}" 
          wx:index="index" 
          data-index="{{index}}"
          bindtap="changeLevel1"
        >
          {{item}}
        </li>
      </ul>
    </view>

    <view class="panel-right">
      <ul>
        <li 
          class="{{active[1] == index? 'active': ''}}" 
          wx:for="{{list[1][active[0]]}}" 
          wx:key="{{index}}" 
          wx:index="index" 
          data-index="{{index}}"
          bindtap="changeLevel2"
        >
          {{item}}
        </li>
      </ul>
    </view>
  </view>
</view>

/components/filter-panel/index.js

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    list: Array,
    active: Array
  },
  /**
   * 组件的方法列表
   */
  methods: {
    changeLevel() {
      this.triggerEvent('changeLevel', {
        level1: this.properties.active[0],
        level2: this.properties.active[1]
      })
    },
    changeLevel1(event) {
      const index = event.target.dataset.index
      this.setData({
        active: [index, 0]
      })
      this.changeLevel()
    },
    changeLevel2(event) {
      const level2 = 'active[1]'
      const index = event.target.dataset.index
      this.setData({
        [level2]: index
      })
      this.changeLevel()
    }
  }
})

(3) 组件内数据传到外部
在这个组件内我定义了changeLevel这个方法,每次点击一级菜单或二级菜单的时候我就用过this.triggerEvent方法把active的值传到组件外部以供使用。

/components/filter-panel/index.js

 methods: {
      changeLevel() {
        this.triggerEvent('changeLevel', {
          level1: this.properties.active[0],
          level2: this.properties.active[1]
        })
      },
      changeLevel1(event) {
        const index = event.target.dataset.index
        this.setData({
          active: [index, 0]
        })
        this.changeLevel()
      },
      changeLevel2(event) {
        const level2 = 'active[1]'
        const index = event.target.dataset.index
        this.setData({
          [level2]: index
        })
        this.changeLevel()
      }
    }

五、总结
这个项目里倒是没用用到组件间的数据传递,所以只是组件和外部的传递,还算是比较简单,但是一定要思考清楚数据的变化状态。

转载链接地址:https://segmentfault.com/a/1190000014474289?utm_source=index-hottest

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
微信小程序是一种基于微信平台的应用程序,它可以在微信中直接运行,无需下载安装。而自定义组件是小程序中的一种重要功能,它允许开发者将一些常用的UI元素封装成组件,以便在不同的页面中复用。 自定义组件具有以下特点: 1. 组件是由wxml、wxss和js文件组成,可以独立定义样式和逻辑。 2. 组件可以接受外部传入的数据,通过属性进行配置。 3. 组件可以触发事件,向外部传递消息。 4. 组件可以包含子组件,形成组件的嵌套结构。 使用自定义组件的步骤如下: 1. 在小程序项目中创建一个新的文件夹,用于存放自定义组件的相关文件。 2. 在该文件夹中创建一个wxml文件,定义组件的结构。 3. 在同一文件夹中创建一个wxss文件,定义组件的样式。 4. 在同一文件夹中创建一个js文件,定义组件的逻辑。 5. 在需要使用该组件的页面中引入组件,并在wxml中使用组件标签。 例如,我们创建一个名为"custom-component"的自定义组件,其文件结构如下: ``` custom-component/ ├── custom-component.wxml ├── custom-component.wxss └── custom-component.js ``` 在custom-component.wxml中定义组件的结构,例如: ```html <view class="custom-component"> <text>{{text}}</text> <button bindtap="handleClick">点击按钮</button> </view> ``` 在custom-component.wxss中定义组件的样式,例如: ```css .custom-component { background-color: #f5f5f5; padding: 10px; } ``` 在custom-component.js中定义组件的逻辑,例如: ```javascript Component({ properties: { text: { type: String, value: '默认文本' } }, methods: { handleClick() { this.triggerEvent('click', { message: '按钮被点击了' }); } } }) ``` 在需要使用该组件的页面中引入组件,并在wxml中使用组件标签,例如: ```html <custom-component text="Hello World" bind:click="handleCustomComponentClick"></custom-component> ``` 以上就是微信小程序自定义组件的简单介绍。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值