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

    1.小程序自定义组件的意义

           小程序允许我们使用自定义组件方式来来构建画面,主要难点在于父向子组件传递数据,子向父组件传递数据和组件插槽功能,实现点击标题数据也发生变化。且所谓的自定义组件,也是由json,wxml,wxss,js四个部分组成

           开发步骤:创建组件→声明组件→使用组件

    1.1 自定义组件components→Tabs

    第一步:创建自定义组件分为几个步骤:

    • 首先创建pages同级文件components,在components下面创建Tabs文件夹,其实此后也就认为该Tabs文件夹为自定义组件了。
    • 其次右击Tabs选择新建component,输入Tabs回车,即可自动生成相应的Tabs.js,Tabs.json,Tabs.wxml,Tabs.wxss
    • 看效果,此时打开Tabs.js与其他js文件差异:

    image

    image

    第二步:声明自定义组件,说白了就是立个flag,哪个页面用就在

    哪个json中声明

    {

    "usingComponents": {

    "Tabs":"../../components/Tabs/Tabs"

    }

    } 例如我们在demo17.json中添加,usingComponet里面是键值对:

    image

    第三步:使用组件

          我们在demo17.wxml中使用<Tabs>00</Tabs>没有显示00,但显示了其自定义组件的里面的信息。

    image


    1.2 自定义组件实战-emmet写法


    注意,设为 Flex 布局以后,子元素的floatclearvertical-align属性将失效。参见:https://www.cnblogs.com/huihuizhang/p/7998902.html

    需要注意的是:tabs.wxml中如果这么写,就写死了,这样就没办法把同样的结构放在不同的页面中,我们需要把标题数据,也就是首页,原创,分类,关于抽离出来,放在tabs.js文件中,我们先尝试把它放在组件内部数据中,稍后再由它(组件内部数据)改成父向子传递数据:

    <view class="tabs">

    <view class="tabs_title">

    <view class="title_item">首页</view>

    <view class="title_item">原创</view>

    <view class="title_item">分类</view>

    <view class="title_item">关于</view>

    </view>

    <view class="tabs_content">内容</view>

    </view>

    第一步案例:自定义组件的样式案例:

    Tabs.js代码

    // components/Tabs/Tabs.js

    Component({

    /**

       * 组件的属性列表

       */

      properties: {

    /*接受父向子传递数据 */

    },

    /**

       * 组件的初始数据

       */

      data: {

        tabs:[{

          id:0,

          name:"首页",

          isActive:true

    },

    {

          id:1,

          name:"原创",

          isActive:false

    },

    {

          id:2,

          name:"分类",

          isActive:false

    },

    {

          id:0,

          name:"关于",

          isActive:false

    },

        ]

    },

    /**

       * 组件的方法列表

       * 在page页面js中,存放事件回调函数的时候,存放在data同级下

       * 在组件页面js中,存放事件回调函数的时候,必须放在methods中

       */

      methods: {

    hanldeItemTap(e){

    // console.log("点击我试试");

    // 1. 绑定点击事件,需要在methods中绑定

    console.log(e)

    // 2. 获取被点击的索引

    const {index}= e.currentTarget.dataset;

    // const {index}=e.currentTarget.dataset

    // 3. 获取原数组

    let {tabs}=this.data;//此处涉及解构思想,复杂类型进行结构时候,复制了一份变量引用而已,它与let tabs=this.data.tabs意思一样

    //当然最严谨的做法是重新拷贝一个数组,如下:

    // let tabs=JSON.prase(JSON.stringify(this.data.tabs));

    // 4. 对数组循环,给每个循环项,选中属性改为false,且给当前的索引项添加激活选中效果即可,因有解构,类似于this.data.tabs.forEach一样

    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);

    this.setData({

    tabs

    })

    }

    }

    })

    Tabs.wxss文件代码:

    /* components/Tabs/Tabs.wxss */

    .tabs{

    border: 1rpx blue solid;

    }

    .tabs_title{

    display: flex;/*伸缩盒子*/

    padding: 10rpx;

    }

    .title_item{

    flex: 1;

    display: flex;/*伸缩盒子*/

    justify-content: center;/*垂直对齐*/

    align-items: center;/*水平对齐*/

    }

    .active{/*激活选中效果*/

    color:red;

    border-bottom: 10rpx solid currentColor;

    }

    .tabs_content{

    border: 1rpx solid yellow;

    }

    Tabs.wxml代码如下:

    <!--components/Tabs/Tabs.wxml-->

    <view class="tabs">

    <view class="tabs_title">

    <!--

        <view class="title_item">首页</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">内容</view>

    </view>

    demo17.WXML代码:

    <!--pages/demo17/demo17.wxml-->

    <Tabs></Tabs>



    第二步:抽离自定义组件内部Tabs.js下面Componet下面的data里面tabs数据抽离到demo17里面,这样才能实现一个自定义组件多处使用,这就存在了父向子组件传值的问题,最为简单的处理方式是:属性值传递:

    image

    具体实现代码如下:

    demo17.html

    <!--pages/demo17/demo17.wxml-->

    <!--

      1.父组件(页面)传递数据通过标签属性

      2.子组件进行接收

    -->

    <!--下面代表意思是,我向子组件Tabs传递了一个属性:属性名aaa 属性值123-->

    <Tabs tabs="{{tabs}}"></Tabs>


    Tabs.wxml

    <!--components/Tabs/Tabs.wxml-->

    <view class="tabs">

    <view class="tabs_title">

    <!--

        <view class="title_item">首页</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">内容</view>

    </view>


    Tabs.js

    // components/Tabs/Tabs.js

    Component({

    /**

       * 组件的属性列表

       */

      properties: {

    /*接受父向子传递数据 */

    // 从demo17.WXML数据

    // aaa:{

    //   // type:表示要接收的数据类型

    //   type:String,

    //   value:''//表示默认值,传123,就123,没有为空

    // }

        tabs:{

          type:Array,

          value:[]

    }

    },

    /**

       * 组件的初始数据

       */

      data: {

    },

    /**

       * 组件的方法列表

       * 在page页面js中,存放事件回调函数的时候,存放在data同级下

       * 在组件页面js中,存放事件回调函数的时候,必须放在methods中

       */

      methods: {

    hanldeItemTap(e){

    // console.log("点击我试试");

    // 1. 绑定点击事件,需要在methods中绑定

    console.log(e)

    // 2. 获取被点击的索引

    const {index}= e.currentTarget.dataset;

    // const {index}=e.currentTarget.dataset

    // 3. 获取原数组

    let {tabs}=this.data;//此处涉及解构思想,复杂类型进行结构时候,复制了一份变量引用而已,它与let tabs=this.data.tabs意思一样

    //当然最严谨的做法是重新拷贝一个数组,如下:

    // let tabs=JSON.prase(JSON.stringify(this.data.tabs));

    // 4. 对数组循环,给每个循环项,选中属性改为false,且给当前的索引项添加激活选中效果即可,因有解构,类似于this.data.tabs.forEach一样

    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);

    this.setData({

    tabs

    })

    }

    }

    })

    Demo17.js

    // pages/demo17/demo17.js

    Page({

    /**

       * 页面的初始数据

       */

      data: {

        tabs:[{

          id:0,

          name:"首页",

          isActive:true

    },

    {

          id:1,

          name:"原创",

          isActive:false

    },

    {

          id:2,

          name:"分类",

          isActive:false

    },

    {

          id:0,

          name:"关于",

          isActive:false

    },

        ]

    },


    image

    第三步:我们进行代码优化上图可知:当我们tab.js的properties接受父数据tabs:{  }(父传子),当我们点击标题内容,关于时,应该会触发点击事件,而此时data数据为空的。因此

      methods: {

    hanldeItemTap(e){

    // console.log("点击我试试");

    // 1. 绑定点击事件,需要在methods中绑定

    console.log(e)

    // 2. 获取被点击的索引

    const {index}= e.currentTarget.dataset;下一步将出错,因为data为空,

    let tabs也就错误了,一句话:isActive值没有改变

    // const {index}=e.currentTarget.dataset

    // 3. 获取原数组

    let {tabs}=this.data;//此处涉及解构思想,复杂类型进行结构时候,复制了一份变量引用而已,它与let tabs=this.data.tabs意思一样

    //当然最严谨的做法是重新拷贝一个数组,如下:

    // let tabs=JSON.prase(JSON.stringify(this.data.tabs));

    // 4. 对数组循环,给每个循环项,选中属性改为false,且给当前的索引项添加激活选中效果即可,因有解构,类似于this.data.tabs.forEach一样

    tabs.forEach((v,i)=>i===index?v.isActive=true:v.isActive=false);

    this.setData({

    tabs

    })

    }

    }

    总结一句话,就是当我们点击标签后,激活事件应该改变,如下图就没有改变,这一步操作就是子向父传数据:

    image






  • 相关阅读:
    学习记录(1):intellij idea 导入gradle
    javac不是内部或外部命令
    robot framework测试https接口实例
    py文件变成可执行exe ,遇到的问题及解决方法
    python 实现爬虫下载网页的方法
    [Usaco2009 Open]干草堆
    【题解】[USACO17JAN]Balanced Photo G
    【题解】[BalticOI 2014]friends
    从恒定状态出发,求解未知状态
    Scoi 组队
  • 原文地址:https://www.cnblogs.com/rango0550/p/13860399.html
Copyright © 2011-2022 走看看