阅读 98

小程序成长之路(二)-- 关于组件

一周左右的时间, 和小程序渐渐的熟悉了起来,今天我们来聊一聊小程序组件--component

1. 为什么会有component?

刚开始入门的几天里最先接触到具有模块化概念的其实是template, 后面才接触到component

猛然见感觉,这两个东西是不是有些重复?

下面我们来仔细分析一下:

首先看下template的例子:

template:

├── template
|   ├── demo-template.wxml
|   └── demo-template.wxss
复制代码

demo-template.wxml

<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>
复制代码

在父容器中引入

index.wxml

<!--引入template-->
<import src="../template/demo-template.wxml" />
<!--index.wxml-->
<view class="container">
  <!--item为index.js中data定义的值,通过es6{{...item}}平铺展开-->
  <template is="msgItem" data="{{...item}}"></template>
</view>
复制代码

template通过上述方法拿到父容器的值,进行渲染。

这看起来完全只能作为数据展示用啊!!!好受限制的感觉!!!

看下官网 模版 介绍部分的最后一句。

模板拥有自己的作用域,只能使用 data 传入的数据 以及 模版定义文件中定义的 模块。

看下标红的部分,就是说,template只能获取父容器传来的数据,相对数据进行操作只能通过<wxs/>

如下:

<template name="msgItem">
    <wxs module="m1">
        var msg = "hello world";
        function changeMsg(msg) {
            var msgChange = msg;
            msgChange = "hello, msg is change!!"
            return msgChange;
        };
        module.exports.message = msg;
        module.exports.changeMsg = changeMsg;
    </wxs>
    <view>
        <view> changebefore: {{msg}} </view> 
        <view> changeafter: {{m1.changeMsg(msg)}} </view> 
        <view> {{m1.message}}</view>
    </view>
</template>
复制代码

总结下template:

父组件每次想要使用模版都要import,有点麻烦,而且数据处理感觉不够灵活,比如父组件传递一个数据给到template, 这个时候template改动了这个数据,想传回给父组件,这个时候感觉就很吃力了(是不是很怀念react!!!)。

于是!!!诞生了好用的component

官网对component的相关介绍:

  1. 自定义组件
  2. Component构造器
  3. 组件间关系
  4. 组件事件
  5. behaviors
  6. 组件模版和样式·小程序

看了这么多,实际来操作下吧!!!

核心逻辑:

  1. 定义组件:

    • compoennt.json中需要说明这是一个组件:

      {
          "component": true
      }
      复制代码
    • compoennt.js中定义构造器: ```js Component({

           behaviors: [],
         
           properties: {
             //父组件给过来的数据
             myProperty: { // 属性名
               type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
               value: '', // 属性初始值(可选),如果未指定则会根据类型选择一个
               observer: function(newVal, oldVal, changedPath) {
                  // 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
                  // 通常 newVal 就是新设置的数据, oldVal 是旧数据
               }
             },
             myProperty2: String // 简化的定义方式
           },
           data: {}, // 私有数据,可用于模版渲染
         
           // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
           attached: function(){},
           moved: function(){},
           detached: function(){},
         
           methods: {
             onMyButtonTap: function(){
               this.setData({
                 // 更新属性和数据的方法与更新页面数据的方法类似
               })
             },
             // 内部方法建议以下划线开头
             _myPrivateMethod: function(){
               // 这里将 data.A[0].B 设为 'myPrivateData'
               this.setData({
                 'A[0].B': 'myPrivateData'
               })
             },
             _propertyChange: function(newVal, oldVal) {
         
             }
           }
         
         })
        ```
      复制代码
  2. 定义一个父组件:

index.json中配置需要的组件:

{
  "usingComponents": {
    <!--引用名:组件实际所在路径-->
    "component-tag-name": "../components/cpt/cpt"
  }
}
复制代码

index.wxml引入组件:

<view>
    <component-tag-name bindshow="onbindshow">
        <!--slot点-->
        <view></view>
    </component-tag-name>
</view>
复制代码

想要通过点击组件触发父级的onbindshow方法,需要在method中使用triggerEvent

Component({
    properties: {}
    methods: {
        onTap: function(){
          var myEventDetail = {} // detail对象,提供给事件监听函数
          var myEventOption = {} // 触发事件的选项
          this.triggerEvent('show', myEventDetail, myEventOption)
        }
    }
})
复制代码

总结:

  1. component比较起template引入更加优雅,不需要在烦人的import。
  2. 功能更强大,不但可以接受渲染数据,而且可以回传数据给父组件。
  3. template使用简单,需要建立的文件较少。

下方干货!!

因为实际工作中项目的原因,使用<map>组件的情况比较多,所以特意写了一个小demo来熟悉,里面有具体的介绍,这里不在赘述:

基于微信小程序的一个记录跑步轨迹demo

关注下面的标签,发现更多相似文章
评论