微信小程序自定义组件(component)

微信小程序自定义组件(component)

1 需求实现一个分类标题的tab组件,可以放在任意页面使用,不需要重复编写

image-20200420085437738.png

2 创建组件文件

​ 在组件文件上右键 新建组件(Tabs),编辑器会自动生成组件文件

image-20200420085541767.png

3 编写组件文件

组件属性方法说明

属性 类型 说明
tabs Array Tabs组件显示的内容信息
binditemChange 绑定接收子组件向父组件传递参数的事件<br />// 接收传递过来的参数是点击tabs的索引
在事件中获取参数: e.detail.index;
<slot>占位符 在<tabs></tabs>自定义中加入任意内容,可以替代子组件中的占位标签

tabs 的示例数据

 tabs:[{
      id:0,
      name:"首页",
      isActive:true
    },{
      id:1,
      name:"原创",
      isActive:false
    },{
      id:2,
      name:"分类",
      isActive:false
    },{
      id:3,
      name:"关于",
      isActive:false
    }]

binditemChange 示例

wxml 页面调用Tabs 组件

<Tabs tabs="{{tabs}}" binditemChange="handItemChange">
 

wxjs文件中添加获取回传参数的自定义事件监听方法

  // 自定义事件 用来接收子组件传递的数据
  handItemChange(e){
    
    // 接收传递过来的参数
    const {index} = e.detail;
    console.log(e)

     // 3 获取原数组,以下写法等价于 let tabs = this.data.tabs;
      // 最好的方法 let tabs = JSON.stringify(this.data.tabs);深拷贝
      
      let {tabs} =  this.data;
       //4 数组循环
        //  1 给每一个循环项 选中属性 改为false 
       //   2 就给当前索引的项 添加激活选中效果就可以了
      //4 数组循环 forEach 遍历数组时, 修改了 v 会导致源数组被修改
      tabs.forEach((v,i)=> i===index?v.isActive=true:v.isActive=false);
      this.setData({
        tabs
      });
  }

Tabs.wxml 页面代码

<view>
</view>
<view class="tabs">
  <view class="tabs-title" >  
    <!-- <view class="title-item active">首页</view>
    <view class="title-item">原创</view>
    <view class="title-item">分类</view>
    <view class="title-item">关于</view> -->
    <view 
      wx:for="{{tabs}}"
      wx:key="id"
      class="title-item {{item.isActive? 'active':''}}" 
      bindtap="hanldeItemTap"
      data-index="{{index}}"
    >{{item.name}}
    </view>
  </view>
  <view class="tabs-content">
  <!-- 
    占位标签
   -->
    <slot></slot>
  </view>
</view>

Tabs.wxcss 样式文件


.tabs{}

.tabs-title{
  display: flex; /*伸缩盒子*/
  padding: 10px 0;
}

.title-item{
  flex:1;
  display: flex;
  justify-content: center; /*水平对齐*/
  align-items: center;/*垂直对齐*/
}
/* 激活选中效果 */
.active{
  color: red;
  border-bottom: 5rpx solid currentColor;
}

.tabs-content{}

Tabs.js js代码

​ 父组件通过属性传递参数到子组件的properties中

// components/Tabs/Tabs.js
// components/Tabs/Tabs.js
Component({
  /**
   * 组件的属性列表
   * 从父组件传递过来的数据
   */
  properties: {
    // 要接受的数据的名称
    tabs:{
      // type 要接受的数据的类型
      type:Array,
      // value 默认值
      value:[]
    }
    
  },

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

  /**
   * 组件的方法列表
   */
  methods: {
    hanldeItemTap(e){
      console.log(e);   
     // 1.绑定点击事件 需要在methods中绑定
      
     //  2 获取被点击的索引
       const {index} = e.currentTarget.dataset;

      //5 触发父组件的自定义事件 同时传递数据给 父组件
      this.triggerEvent("itemChange",{index});
    },
  }
})

4 组件的调用

1 在页面的json配置文件中引用自定义组件(Tabs)

{
  "usingComponents": {
    "Tabs":"/components/Tabs/Tabs"
  }
}

2 在页面中引用自定义组件标签

父组件通过属性的形式给子组件传递参数

子组件通过事件的形式式向父组件传递参数

流程 :

  1. tabs="{{tabs}} 将当前页面的 tabs 传递给子组件<Tabs>

  2. 子组件<Tab> 回去到值,遍历tabs中的数据,将标题信息展现到页面

  3. 用户点击子组件<Tabs>的标题块,触发自定义事件itemChange

  4. 子组件的自定义事件 itemChange 获取到点击标题的索引,通过触发当前页面的自定义方法temChange,将索引值传递给当前页面

<!--
  1 父组件 向传递子组件 传递数据  通过 标签属性的方式来传递的
    1 在子组件上进行接收
    2 把这个数据当成是data中的数据直接用即可
  2 子向父传递数据 通过事件的方式传递
    1 在子组件的标签中加入一个 自定义事件

-->
<!-- 
  tabs 标题数组 传给子组件
  binditemChange 子组件回传tabs被点击的标题的index
  block 替代子组件中的占位标签 <slot> 
 -->
<Tabs tabs="{{tabs}}" binditemChange="handItemChange">

  <block wx:if="{{tabs[0].isActive}}">0</block>
  <block wx:elif="{{tabs[1].isActive}}">1</block>
  <block wx:elif="{{tabs[2].isActive}}">2</block>
  <block wx:elif="{{tabs[3].isActive}}">3</block>
</Tabs>

3 在js文件中加入要传递给子组件的数据, 以及从子组件中取值的方法

Page({
  /**
   * 页面的初始数据
   */
  data: {
    tabs:[{
      id:0,
      name:"首页",
      isActive:true
    },{
      id:1,
      name:"原创",
      isActive:false
    },{
      id:2,
      name:"分类",
      isActive:false
    },{
      id:3,
      name:"关于",
      isActive:false
    }]
  },
  // 自定义事件 用来接收子组件传递的数据
  handItemChange(e){
    
    // 接收传递过来的参数
    const {index} = e.detail;
    console.log(e)

     // 3 获取原数组,以下写法等价于 let tabs = this.data.tabs;
      // 最好的方法 let tabs = JSON.stringify(this.data.tabs);深拷贝
      
      let {tabs} =  this.data;
       //4 数组循环
        //  1 给每一个循环项 选中属性 改为false 
       //   2 就给当前索引的项 添加激活选中效果就可以了
      //4 数组循环 forEach 遍历数组时, 修改了 v 会导致源数组被修改
      tabs.forEach((v,i)=> i===index?v.isActive=true:v.isActive=false);
      this.setData({
        tabs
      });
  }
})
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容