zoukankan      html  css  js  c++  java
  • 微信小程序-自定义组件

    十年河东,十年河西,莫欺少年穷

    学无止境,精益求精

    1、首先我们创建一个基本的小晨旭组件【/Components/Tabs/Tabs】,如下

    Tabs.js

    // pages/Components/Tabs/Tabs.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
    
      },
    
      /**
       * 组件的初始数据
       */
      data: {
        tabs: [{
            id: 0,
            name: "首页",
            isactive: true
          },
          {
            id: 1,
            name: "原创",
            isactive: false
          },
          {
            id: 2,
            name: "分类",
            isactive: false
          },
          {
            id: 3,
            name: "关于",
            isactive: false
          }
        ]
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        tabitemchange: function (e) {
          const {
            index
          } = e.currentTarget.dataset;
          let list = this.data.tabs;
          list.forEach((v, i) => {
            console.log(v);
            console.log(i);
            i == index ? v.isactive = true : v.isactive = false;
          });
          this.setData({
            tabs: list
          });
        }
      }
    })

    Tabs.wxss

    /* pages/Components/Tabs/Tabs.wxss */
    .tabs{
    
    }
    .tabs_title{
      display: flex;
      padding:10rpx;
    }
    .tabs_item{
      flex: 1;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .active{
      color:red;
      border-bottom:4rpx solid red;
    }
    .tabs_content{}

    Tabs.wxml ,注:tabitemchange 点击方法传参为:data-index 及 wx:for 中 item 的索引

    <view class="tabs">
      <view class="tabs_title">
        <view 
        class="tabs_item {{item.isactive?'active':''}}" 
        wx:for="{{tabs}}" 
        wx:key="id"
        bindtap="tabitemchange"
        data-index="{{index}}"
        wx:for-index="index"
        wx:for-item="item"
        >
        {{item.name}}
      </view>
        <!-- <view class="tabs_item active" bindtap="tabitemchange">首页</view>
        <view class="tabs_item">原创</view>
        <view class="tabs_item">分类</view>
        <view class="tabs_item">关于</view> -->
      </view>
      <view class="tabs_content">内容</view>
    </view>

    在page页面中,引用该组件,如下

    demo17.json

    {
      "usingComponents": {"Tabs":"../Components/Tabs/Tabs"}
    }

    demo17.wxml

    <Tabs> 
      
    </Tabs>

    这样,demo17的页面展示如下

     以上我们就简单构建了一个组件。

    在上述构造中,父组件为页面demo17.wxml ,子组件为tabs.wxml,那么组件之间怎么进行传值呢?

    父向子传值

    首先演示下父向子传值的简易demo,如下

    在父组件中,自定义一个属性叫:fatherData

    <!--pages/demo17/demo17.wxml-->
    <Tabs fatherData="请叫我爸爸"> 
    </Tabs>

    在子组件的属性中,创建 对象fatherData ,并声明 Type 属性为字符串,value 默认为空值

    // pages/Components/Tabs/Tabs.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        fatherData:{
          type:String,
          value:""
        }
      },

    最后,在Tabs.wxml中添加如下代码

      <view>
      我接受到的值为:{{fatherData}}
    </view>

    保存,并查看效果

    这样,父传子就简单的完成了。

    现在,我们传递变量给子组件,在demo17.js 中创建tabs数组如下:

    // pages/demo17/demo17.js
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        tabs: [{
          id: 0,
          name: "首页",
          isactive: true
        },
        {
          id: 1,
          name: "原创",
          isactive: false
        },
        {
          id: 2,
          name: "分类",
          isactive: false
        },
        {
          id: 3,
          name: "关于",
          isactive: false
        }
      ]
      },
    })

    然后在demo17.wxml 中修改如下:

    <!--pages/demo17/demo17.wxml-->
    <Tabs tabs="{{tabs}}"> 
    </Tabs>

    最后,在子组件Tab.js中申明要接收的tabs的类型及默认值

    // pages/Components/Tabs/Tabs.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        tabs:{
          type:Array,
          value:[]
        }
      },

    此时保存,并查看页面效果,和之前一样

    但是,此时,子组件的tabitemchange 点击事件就有问题了,如下:

    // pages/Components/Tabs/Tabs.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        tabs:{
          type:Array,
          value:[]
        }
      },
    
      /**
       * 组件的初始数据
       */
      data: {
      
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        tabitemchange: function (e) {
          const {
            index
          } = e.currentTarget.dataset;
          let list = this.data.tabs;
          list.forEach((v, i) => {
            console.log(v);
            console.log(i);
            i == index ? v.isactive = true : v.isactive = false;
          });
          this.setData({
            tabs: list
          });
        }
      }
    })
    View Code

     此时,子组件的data 中并没有tabs 变量,因此 this.setData({}) 不生效,也不报错

    现在,tabs 变量是父组件传递过来的,那么,我们真正要修改的是父组件的tabs变量,这时,就需要子向父传值了,可参考:https://www.bilibili.com/video/BV1nE41117BQ?p=40

    子向父传值

     子向父传值时,需要使用  this.triggerEvent("itemChange",index); 绑定一个触发事件,并传递 index 变量

    因此,在tabs.js 中 我们修改如下:

    // pages/Components/Tabs/Tabs.js
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        tabs:{
          type:Array,
          value:[]
        }
      },
    
      /**
       * 组件的初始数据
       */
      data: {
      
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        tabitemchange: function (e) {
          const  index= e.currentTarget.dataset.index;
          this.triggerEvent("itemChange",index);
        }
      }
    })

    在父组件中,我们接受这个触发事件,如下:

    <!--pages/demo17/demo17.wxml-->
    <Tabs tabs="{{tabs}}" binditemChange="itemChange"> 
    </Tabs>

    在父组件中,定义itemChange方法

    // pages/demo17/demo17.js
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        tabs: [{
          id: 0,
          name: "首页",
          isactive: true
        },
        {
          id: 1,
          name: "原创",
          isactive: false
        },
        {
          id: 2,
          name: "分类",
          isactive: false
        },
        {
          id: 3,
          name: "关于",
          isactive: false
        }
      ]
      },
      itemChange:function(e){
        console.log(e)
        const  index= e.detail; //传递过来的值 一般都放在 e.detail 中
        let list = this.data.tabs;
        list.forEach((v, i) => {
          i == index ? v.isactive = true : v.isactive = false;
        });
        this.setData({
          tabs: list
        });
      }
    })

    这样,父组件就可以根据自个的需求,进行导航条的定义了。

    最后,我们根据条目的切换,显示的内容变成动态的,这时,我们需要使用一个标签,插槽

    插槽---Slot

    首先在子组件中,内容部分,用插槽替代,如下

      <view class="tabs_content">
        <slot></slot>
      </view>

    在父组件中,填充插槽

    <!--pages/demo17/demo17.wxml-->
    <Tabs tabs="{{tabs}}" binditemChange="itemChange"> 
      <view>
        我要替代插槽
      </view>
    </Tabs>

    效果如下

     最后,我们将我要替代插槽改成变量,即可完成内容的动态化

    <!--pages/demo17/demo17.wxml-->
    <Tabs tabs="{{tabs}}" binditemChange="itemChange"> 
     <block wx:if="{{tabs[0].isactive}}">首页被选中</block>
     <block wx:elif="{{tabs[1].isactive}}">原创被选中</block>
     <block wx:elif="{{tabs[2].isactive}}">分类被选中</block>
     <block wx:else="{{tabs[3].isactive}}">关于被选中</block>
    </Tabs>

    效果

     @天才卧龙的博客

  • 相关阅读:
    如何重新加载 Spring Boot 上的更改,而无需重新启动服务器?
    FileUpload拦截器
    aspnet网页刷新
    查看SQL表的详细信息
    学习GDI+ (1)
    设计模式简单工厂模式
    对数据库表操作,统一的方法。
    随机产生300道四则运算
    略谈从计算机专业,再到软件构建的初识
    #在android studio中维护日程管理系统
  • 原文地址:https://www.cnblogs.com/chenwolong/p/slot.html
Copyright © 2011-2022 走看看