原生小程序 - 组件选项

178 阅读5分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情

插槽

组件的插槽也是为了让我们封装的组件更加具有扩展性, 让使用者可以决定组件内部的一些内容到底展示什么

单个插槽

父组件

<Cpn>
  <view>组件插槽中的值</view>
</Cpn>

子组件

<view>
  <slot />
</view>

小程序中虽然可以使用插槽,但是并不支持插槽的默认值

为此只能退而求其次,使用别的方式来模拟小程序插槽的默认值

父组件

<Cpn>
  <view>Lorem, ipsum.</view>
</Cpn>

<view>------</view>

<Cpn />

子组件

html

<view>
  <!-- 有插槽内容的时候,显示在view.content下 -->
  <view class="content">
    <slot />
  </view>
  <!-- 没有插槽内容的时候,就显示empty下的内容 -->
  <view class="empty">
    这是插槽的默认值
  </view>
</view>

css

/* 默认情况下, 默认插槽内容是不显示的  */
.empty {
  display: none;
}

/* 只有当content中没有内容的时候,才会显示默认插槽中的内容 */
.content:empty + .empty {
  display: block;
}

多个插槽

如果需要在小程序中,使用多插槽,必须在组件中开启

Component({
  options: {
    multipleSlots: true
  }
})

父组件

<Cpn>
  <text slot="left">left</text>
  <text slot="center">center</text>
  <text slot="right">right</text>
</Cpn>

子组件

<view class="m-slot">
  <view class="left">
    <!--
			和vue一样,使用多个插槽的时候,必须给插槽具名
			否则所有的符合条件的插槽都会重复插入内容

			在小程序中,使用具名插槽的方式和vue早期使用具名插槽的方式是一致的
		-->
    <slot name="left" />
  </view>
  
  <view class="center">
    <slot name="center" />
  </view>

  <view class="right">
    <slot name="right"  />
  </view>
</view>

behavior

behaviors 是用于组件间代码共享的特性,类似于一些编程语言中的 “mixins”

每个 behavior 可以包含一组属性、数据、生命周期函数和方法

组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用

每个组件可以引用多个 behavior ,behavior 也可以引用其它 behavior

其实无论是组件还是页面,都可以通过behavior来混入需要共享的特性

/mixins/count

// 如果在小程序中需要定义混入
// 需要使用Behavior函数
export const countMixin = Behavior({
   data: {
     count: 100
   },

   methods: {
     increment() {
       this.setData({
         count: this.data.count + 1
       })
     }
   }
})

组件

<view>{{ count }}</view>
<button bindtap="increment">+1</button>
// 在小程序中引入mixin文件的时候,只能使用相对路径,不可以使用以/开头的绝对路径
import { countMixin } from '../../mixins/count'

Component({
  // 和vue中的mixins一样,小程序中的mixins使用的也是数组形式
  behaviors: [countMixin]
})

生命周期

组件的生命周期

组件的生命周期,指的是组件自身的一些函数,这些函数在特殊的时间点或遇到一些特殊的框架事件时被自动触发

其中,最重要的生命周期是 created attached detached ,包含一个组件实例生命流程的最主要时间点

自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes 字段内进行声明(这是推荐的方式,其优先级最高)

image.png

Component({
  // 在lifetimes选项中定义组件的生命周期
  lifetimes: {
    created() {
      // created阶段只是组件被创建,并没有被挂载组件实例
      // 所以在created阶段不能使用this.setData方法,会静默失效
      console.log('组件被创建时回调的生命周期')
    },

    attached() {
      console.log('组件准备被挂载到dom树时的生命周期 - beforeMount')
    },

    ready() {
      console.log('组件被挂载到页面上的时候执行的回调 - mounted')
    },

    detached() {
      console.log('组件被移除的时候执行的回调')
    }
  }
})

组件所在页面的生命周期

还有一些特殊的生命周期,它们并非与组件有很强的关联

但有时组件需要获知当前组件所在的页面处于什么状态的时候,以进行相应的操作

这样的生命周期称为“组件所在页面的生命周期”,在 pageLifetimes 定义段中定义

image.png

Component({
  // 在组件中监听页面的生命周期
  pageLifetimes: {
    show() {
      console.log('show')
    },

    hide() {
      console.log('hide')
    }
  }
})

Observers

observers的功能和vue中watch选项的功能是一致的

小程序中的数据监听器用于监听和响应任何属性和数据字段的变化,从而执行某些特定操作

小程序中的数据监听器(observer)只能在组件中使用

Component({
  data: {
    userInfo: {
      name: 'Klaus',
      age: 23
    }
  },

  
  observers: {
    // 当userInfo的name属性被修改的时候 或者userInfo本身被修改的时候, 都会触发这个observer
    // 小程序的observer和vue中的watch不一样的一点是,小程序中的observer只提供新值,并不提供旧值
    'userInfo.name'(newV) {
      console.log(newV)
    },
    
    // 只有userInfo本身发生修改的时候,才会触发
    'userInfo'(newV) {
      console.log(newV)
    },
    
    // 可以监听多个值
    'userInfo.name, userInfo,age'(newV) {
      console.log(newV)
    },
    
    // 上述监听多个值的写法 等价于 下述写法
    // 表示当userInfo下的任意属性发生改变的时候,都会触发对应的observer
    // newV的值是userInfo的新值
    'userInfo.**'(newV) {
      console.log(newV)
    }
    
    // 小程序中的observer也可以监听数组中某一项的改变 (vue中不允许)
    'users[0]'(newV) {
  		 console.log(newV)
		}
  },

  methods: {
    handleTap() {
      // 设置某一个对象中具体的属性值
      this.setData({
        'userInfo.name': 'Steven'
      })
    }
  }
})

纯数据字段

纯数据字段指代的是那些值应用于业务逻辑中的,不用于界面渲染的数据字段

这些字段即不会展示在界面上,也不会传递给其它组件,所以我们可以将这里字段定义为纯数据字段

如果对应字段在小程序中被定义为纯数据字段,那么它们将仅仅被记录在 this.data

而不参与任何界面渲染过程,这样有助于提升页面更新性能

指定“纯数据字段”的方法是在 Component 构造器的 options 定义段中指定 pureDataPattern 为一个正则表达式,字段名符合这个正则表达式的字段将成为纯数据字段

所以纯数据字段也只能在组件中进行使用

Component({
  options: {
    // 定义纯数据字段的匹配格式
    // 这里指代的是所有在data中以下划线开头的字段都应该被解析为纯数据字段
    pureDataPattern: /^_/
  },

  data: {
    _count: 0
  },

  methods: {
    handleTap() {
      this.data._count++
      console.log(this.data._count)
    }
  }
})