1. The background

Some time ago in a popup window screening function, there is a radio option, there are multiple options, which may also include a custom option (for example, click on the button continue to pop up after the date or time selection), start writing code is poorly written, lead to bad behind maintenance, this two days make it out into a base component (partial) our business and the business component.

2. Base Component (buttonList)

<template>
  <view class="button-list">
    <text
      wx:for="{{optionsList}}"
      wx:key="text"
      bindtap="onClick(item, index)"
      wx:class="{{ ['button-list_item', activedValue[item.text] ? 'button-list_active-item' : '']}}"
      >{{ item.text }}</text
    >
  </view>
</template>
Copy the code
 properties: {
      / * * [{text: String, show the text value: a String | | Number | | Boolean and so on Selected value}] * /
      // List of options
      optionsList: Array.// The default value is selected (item is required for further extensibility)
      defaultValue: {
        type: Array.value: []}},data() {
      return {
        activeValue: []}},lifetimes: {
      // When the component is activated, a separate copy of data is saved as the current selected item
      attached() {
        this.activeValue = [...this.defaultValue]
      }
    },
    observers: {
      // Trigger the parent component's change event and pass the value to the parent component when the selected button changes.
      activeValue(newVal) {
        this.triggerEvent('change', newVal)
      }
    },
    computed: {
      // Handles the currently selected button style
      // The framework does not support using arrays in templates to determine whether a value exists
      // So we need to do a conversion here
      activedValue() {
        const activeObject = {}
        this.optionsList.forEach(optionsItem= > {
          this.activeValue.forEach(defaultItem= > {
            const defalutText = defaultItem.text
            const optionsText = optionsItem.text
            if (defalutText === optionsText) {
              activeObject[`${defalutText}`] = defalutText
            }
          })
        })
        return activeObject
      }
    },
    methods: {
      // Handle the click event
      // Click the control button repeatedly to deselect
      onClick(item, index) {
        const idx = this.activeValue.findIndex(activeItem= > activeItem.text === item.text)
        idx === -1 ? this.activeValue.push(item) : this.activeValue.splice(idx, 1)
        this.triggerEvent('click', { item, index }) // I pass the index so that when I use the business component, I can use the index value to determine whether I click on a custom option to fulfill my business requirements}}Copy the code

3. Business Component (buttonGroup)

<template>
  <view class="button-group">
    <view class="button-group_title">{{ groupInfo.title }}</view>
    <button bind:click="handleClick" bind:change="handleChange" optionsList="{{groupInfo.optionsList}}" defaultValue="{{groupInfo.defaultValue}}" />
  </view>
</template>
Copy the code
    properties: {
      /** [{title: String title optionsList: same as above}] */
      groupInfo: Object
    },
    methods: {
      // Handle click events for child components
      handleClick({ detail }) {
        // const {item, index} = detail
        this.triggerEvent('click', detail) // Pass to the outside
      },
      // Handle the change in the selected value of the child component
      handleChange({ detail }) {
        this.triggerEvent('change', detail) // Pass to the parent to update the currently active value when the selected value of the child component changes}}Copy the code

4. Example

<button-group groupInfo="{{groupInfo}}" bind:click="onClick" bind:change="onChange" />

Copy the code
    data() {
      return {
      groupInfo: {
          title: 'city'.optionsList: [{text: 'guangzhou'.value: 'GuangZhow'
            },
            {
              text: 'shenzhen'.value: 'ShenZhen'
            },
            {
              text: 'Shanghai'.value: 'ShangHai'}].defaultValue: [{text: 'guangzhou'.value: 'GuangZhow'
            },
            {
              text: 'shenzhen'.value: 'ShenZhen'}},// The currently selected items
        activeInfo: [].}},methods: {
      onclick({ detail }) {
        console.log(detail) // {item, index}
      },
      onchange({ detail }) {
        this.activeInfo = detail // Bind the currently selected value}}Copy the code

In this article, I will not do much about CSS styles, but simply share my thinking and practice on component packaging during development.

5. A better way

In official document have relations suitable for small program expounds the relationship between the two custom components, may use the there will be more reasonable solution developers.weixin.qq.com/miniprogram…

Writing is actually very simple, but for beginners, I have made great progress. Hopefully in the future I’ll be able to write better components before I develop them, rather than re-examine myself after I’ve done the requirements. The road is still long, I still need to work hard ~