微信小程序:自定义组件的数据传递
一、前言
如果小程序中有可复用的UI且具有一定的功能性,就可以使用自定义组件将其封装起来。下面介绍一个简单的组件和一个复杂的组件。
二、简单的组件(计数器)
1. 组件功能介绍
这个组件常见于外卖软件中,用于记录想要购买的商品的数量。初始化的时候只有一个加号,点击加号以后出现数字和减号,并最后将数字传到组件外供外部使用。
2. 创建组件
首先在根目录创建components文件夹(或者你喜欢的地方),然后创建num-controller文件夹(我取的组件名字),在这个文件夹上点击右键新建一个component,名字依然叫做num-controller。
num-controller.wxml
<view class="num-controller">
<view class="iconfont icon-jianshao sub-btn" hidden="{{num<1}}" bindtap="sub"></view>
<view class="goods-num" hidden="{{num<1}}">{{num}}</view>
<view class="iconfont icon-zengjia add-btn" bindtap="add"></view>
</view>
这段代码就是加减两个按钮和一个数字,因为我使用的是字体图标所以view里什么都没有。
num-controller.json
{
"component": true,
"usingComponents": {}
}
这个文件在创建component的时候会自动写入这段代码。
num-controller.js
Component({
/**
* 组件的属性列表
*/
properties: {
num: Number
},
/**
* 组件的初始数据
*/
data: {
},
/**
* 组件的方法列表
*/
methods: {
add() {
this.setData({
num: this.data.num + 1
})
this.triggerEvent('numChange', this.data.num);
},
sub() {
if(this.data.num > 0) {
this.setData({
num: this.data.num - 1
})
}
this.triggerEvent('numChange', this.data.num);
}
}
})
组件内部接收一个参数num,类型是Number;
点击加号触发add方法,首先把init状态变为false,然后数字+1,同时触发numChange方法将改变的数字传到组件外部;
点击减号触发sub方法,数字-1,如果数字为0则把init状态变为true,同时触发numChange方法将改变的数字传到组件外部。
将组件数据传到外部的方法为this.triggerEvent('方法名',{要传递的数据})。
3. 引入组件
假如我要在index.wxml里引入组件:
<num-controller num="{{num}}" bindnumChange="numChange"></num-controller>
index.json
{
"usingComponents": {
"num-controller": "/components/num-controller/num-controller"
}
}
在json文件里注册组件。
index.js
data: {
num: 1
},
numChange(e) {
const numi = e.detail;
}
data里的num是从组件外传入的num,在numChange方法里用e.detail可以拿到组件内部通过this.triggerEvent传出来的数据,然后根据业务需求做逻辑修改。
三、复杂的组件(筛选面板)
一个二级菜单,点击左边(一级)会改变右边(二级)的展示。
1. 创建组件并引入
组件内部:
// filter-panel.wxml
<view class="filter-panel">
<view class="panel-container">
<view class="panel-left">
...
</view>
<view class="panel-right">
...
</view>
</view>
</view>
// filter-panel.json
{
"component": true
}
组件外部:
// index.wxml
<filter-panel></filter-panel>
index.json
{
"usingComponents": {
"filter-panel": "/components/filter-panel/filter-panel-component"
}
}
这样就成功引入组件啦~(说真的组件化做好了非常舒服,后期会省很多力气)
2.组件与外部的数据传递(重点)
(1) 固定数据渲染
// filter-panel-component.js
Component({
/**
* 组件的属性列表
*/
properties: {
mode: String,
panel: String,
text: Array,
active: Array
},
/**
* 组件的初始数据
*/
data: {
filterActive:[]
},
/**
* 组件的方法列表
*/
methods: {
...
}
})
// index.wxml
<filter-panel mode="mode1" panel="panel1" text="{{panel1Text}}" active="{{panel1Active}}"></filter-panel>
// index.js
panel1Text: [
{
'location': '附近',
'choice': ['不限', '1km', '2km', '3km']
}, {
'location': '地铁站',
'choice': ['江汉路', '光谷广场', '陶家岭', '六渡桥']
}
],
panel1Active: [0, 0]
从组件外向组件内传递数据,直接在外部引入的组件上传。
这里我传入了4个数据,
mode代表筛选面板的模式,虽然这里只写了一种,但是实际上有三种形式,我写在了一个组件里,所以每次引入的时候都要指定mode。
panel代表是第几个面板,虽然模式有三种,但是首页有四个面板,其中有两个的mode是相同的,为了区分每一个面板传入panel。
panel1Text是渲染的数据。
panel1Active是用户选择的数据。
到这里组件已经可以正常展示了,但是点击显示选中项还未实现。
(2) 可变数据渲染
控制组件active项的是外部的数据panel1Active: [0, 0],通过组件传到了内部,在组件内部:
// filter-panel-component.js
properties: {
mode: String,
panel: String,
text: Array,
active: Array
},
data: {
filterActive:[]
},
attached() {
this.dataInit();
},
/**
* 组件的方法列表
*/
methods: {
dataInit() {
let active = this.properties.active;
this.setData({
filterActive: active
})
},
_chooseMode1Left(e) {
let mode1LeftIndex = e.currentTarget.dataset.index;
let mode1Active = this.data.filterActive;
if (mode1LeftIndex == 0) {
mode1Active.fill(0, 1, 2);
} else {
mode1Active.fill(-1, 1, 2);
}
mode1Active.fill(mode1LeftIndex, 0, 1);
this.setData({
filterActive: mode1Active
})
},
_chooseMode1Right(e) {
let mode1RightIndex = e.currentTarget.dataset.index;
let mode1Active = this.data.filterActive;
mode1Active.fill(mode1RightIndex, 1, 2);
this.setData({
filterActive: mode1Active
})
wx.setStorageSync(this.properties.panel, this.data.filterActive);
this.triggerEvent('closePanel', {});
}
}
dataInit方法指把外部传进来的active数组赋给内部的私有变量filterActive,然后在内部控制点击的active项。
// index.wxml
<view class="filter-panel mode1" wx:if="{{mode == 'mode1'}}">
<view class="panel-container">
<view class="panel-left">
<view class="left-item {{filterActive[0] == idx1?'active':''}}" bindtap="_chooseMode1Left" wx:for="{{text}}" wx:for-index="idx1" data-index="{{idx1}}">{{item.location}}</view>
</view>
<view class="panel-right {{filterActive[0] == idx1?'':'hide'}}" wx:for="{{text}}" wx:for-index="idx1" data-index="{{idx1}}">
<view class="right-item {{filterActive[1] == idx2?'active':''}}" bindtap="_chooseMode1Right" wx:for="{{item.choice}}" wx:for-index="idx2" data-index="{{idx2}}">
<span>{{item}}</span>
<view class="iconfont icon-correct" hidden="{{filterActive[1] != idx2}}"></view>
</view>
</view>
</view>
</view>
_chooseMode1Left和_chooseMode1Right是两个私有方法,官方建议是在函数名前面加上下划线以便区分。
在点击右侧的时候触发外部的方法closePanel。
(3) 组件内数据传到外部
triggerEvent方法可以把组件内部的数据传到外面,触发组件外的事件。它接收3个参数:
this.triggerEvent('myevent', myEventDetail, myEventOption);
myEventDetail和myEventOption都是对象,myEventDetail是传到组件外的数据,myEventOption有三个参数可以设置:
bubbles 默认false 事件是否冒泡
composed 默认false 事件是否可以穿越组件边界
capturePhase 默认false 事件是否拥有捕获阶段
但是这里我并没有用triggerEvent将数据传出去,因为我这么做了之后发现组件内外的数据开始同步了,这不是我想要的效果。在组件外部有可能点击其他地方隐藏筛选面板,就算用户点击了左侧也不改变上一次保留的数据,所以我用wx.setStorageSync来保存上一次用户确定的数据。如果用户点击其他地方隐藏面板,则从Storage里取出真实的数据渲染。
在组件外部可以这样操作内部的方法:
// index.js
onReady() {
this.panel1 = this.selectComponent("#panel1");
},
showPanel(e) {
this.panel1.dataInit();
},
index.wxml
<filter-panel mode="mode1" panel="panel1" text="{{panel1Text}}" active="{{panel1Active}}" bind:closePanel="closePanel" id="panel1"></filter-panel>
通过id获取到组件,然后调用组件内的方法。可以在每次显示筛选面板的时候初始化数据。这就是我最后使用的解决办法。
三、总结
这个项目里倒是没用用到组件间的数据传递,所以只是组件和外部的传递,还算是比较简单,但是一定要思考清楚数据的变化状态。
微信小程序:自定义组件的数据传递的更多相关文章
- 微信小程序自定义组件,提示组件
微信小程序自定义组件,这里列举了一个常用的提示自定义组件,调用自定义组件中的方法和字段.仅供参考和学习. 编写组件: 在根目录下添加“components”目录,然后像添加Page页面一样添加自定义组 ...
- 微信小程序自定义组件
要做自定义组件,我们先定一个小目标,比如说我们在小程序中实现一下 WEUI 中的弹窗组件,基本效果图如下. Step1 我们初始化一个小程序(本示例基础版本库为 1.7 ),删掉里面的示例代码,并新建 ...
- 微信小程序自定义组件的使用以及调用自定义组件中的方法
在写小程序的时候,有时候页面的内容过多,逻辑比较复杂,如果全部都写在一个页面的话,会比较繁杂,代码可读性比较差,也不易于后期代码维护,这时候可以把里面某部分功能抽出来,单独封装为一个组件,也就是通常说 ...
- 微信小程序自定义组件-下拉框
这个是网址https://www.cnblogs.com/zjjDaily/p/9548433.html 微信小程序之自定义select下拉选项框组件 知识点:组件,animation,获取当前点击元 ...
- 微信小程序自定义组件实现
官方从 1.6.3 开始对于自定义组件这一块有了比较大的变动,首先比较明显的感觉就是文档比以前全多了,有木有!,现在小程序支持简洁的组件化编程,可以将页面内的功能模块抽象成自定义组件,以便在不同的页面 ...
- 微信小程序自定义组件封装及父子间组件传值
首先在我们可以直接写到需要的 page 中,然后再进行抽取组件,自定义组件建议 wxzx-xxx 命名 官网地址:https://developers.weixin.qq.com/miniprogra ...
- 微信小程序 自定义组件(stepper)
项目目录: 步骤一:创建组件 声明这一组文件为自定义组件 stepper.json { "component": true, "usingComponents" ...
- 微信小程序 自定义组件(modal) 引入组件
项目结构: 步骤一:创建组件 声明这一组文件为自定义组件 modal.json { "component": true, // 自定义组件声明 "usingCompone ...
- 微信小程序 自定义组件 多列选择器 对象数组 ObjectArray 自关联 三级联动
使用方法 在 Page.json 注册组件 { "usingComponents": { "address-picker": "/component/ ...
- 微信小程序自定义组件——接受外部传入的样式类
https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/wxml-wxss.html 外部样式类 有时, ...
随机推荐
- 洛谷训练P1008(循环+暴力)
1 #include<stdio.h> 2 #include<string.h> 3 int a[10]; 4 int main(){ 5 for (int x=123;x&l ...
- 解决Js中的resize事件执行两次的方法
问题: 页面自适应的时候需要用到js的resize事件,但在执行过程中发现只要触发resize事件就会执行2次 原生js: window.onresize = function(){ console. ...
- JZ-003-从尾到头打印链表
从尾到头打印链表 题目描述 输入一个链表,按链表从尾到头的顺序返回一个ArrayList. 题目链接: 从尾到头打印链表 代码 import java.util.ArrayList; /** * 标题 ...
- Python 学习路线(2022)
原文链接: Python 学习路线(2022) 前几天整理了一份 Go 学习路线(2022),广受好评.那么趁火打劫,不是,是趁热打铁,又整理了一份 Python 学习路线. 内容依然是从入门到进阶, ...
- Guava中这些Map的骚操作,让我的代码量减少了50%
原创:微信公众号 码农参上,欢迎分享,转载请保留出处. Guava是google公司开发的一款Java类库扩展工具包,内含了丰富的API,涵盖了集合.缓存.并发.I/O等多个方面.使用这些API一方面 ...
- Kernel pwn 基础教程之 ret2usr 与 bypass_smep
一.前言 在我们的pwn学习过程中,能够很明显的感觉到开发人员们为了阻止某些利用手段而增加的保护机制,往往这些保护机制又会引发出新的bypass技巧,像是我们非常熟悉的Shellcode与NX,NX与 ...
- 从原理学习Java反序列化
1 序列化与反序列化 1.1 概念 序列化: 将数据结构或对象转换成二进制串的过程 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程 1.2 使用场景 当你想把的内存中的对象状态 ...
- java反射获取类的成员函数,成员变量,构造函数
package com.imooc.reflect;import javax.sound.midi.Soundbank;import java.lang.reflect.Constructor;imp ...
- windows 2008 R2磁盘清理
记录一次由于磁盘空间满,IIS使前端程序报500的事故 由于导出Api部署在IIS服务器,在程序调用导出Api会报500 发现windows服务器C盘已满 下面处理过程 只需复制cleanmgr.ex ...
- BUAA_DS_北航数据结构:输出全排列
输入一个数 \(n\),输出 \(1\sim n\) 的所有全排列,每个排列占一行,每个字符保留 \(5\) 个场宽.勤奋的同学一定已经开始打表了是吧. 说是能做肯定不是骗大家,那怎么做呢~ 其实回溯 ...