Vue - Custom Components How-way binding

Foreword

At any language or framework, we promote reusability of code. The same is true for Vue, the same code can be packaged into logical components, in addition to reuse, it is more important to improve development efficiency unified management. I really had to take over a project, will be used more than one page list of the package did not go to the list of components, with a little modification, each page had to add. I am sure that there is no use of component-based development projects Vue is soulless. So how to package an elegant and high reusability of components to be our essential skills.

Tab custom components

First look at a realization Tab component to see if it there is a problem, where you can improve?

effect

Package

<template>
  <div class="tabs">
    <div 
      class="tab-item" 
      :class="{'tab--active':item===activeName}"
      v-for="(item,index) in tabs" 
      :key="index" 
      @click="tabChange(item)">
      {{item}}
    </div>
  </div>
</template>

<script>
export default {
  props:{
    tabs:{
      type: Array,
      default: ()=> []
    },
    activeName:{
      type: String,
      default: ''
    }
  },
  methods:{
    tabChange(item){
      this.$emit('tabChange',item)
    }
  },
}
</script>

use

<template>
  <div>
    <Tabs :tabs="tabs" :activeName="activeName" @tabChange="tabChange" />
  </div>
</template>

<script>
import Tabs from '../components/Tabs'
export default {
  components:{
    Tabs
  },
  data(){
    return{
      tabs:['黄金体验','败者食尘','绯红之王','白金之星','波纹疾走'],
      activeName: '黄金体验'
    }
  },
  methods:{
    tabChange(item){
      this.activeName = item
    }
  },
}
</script>

analysis

The biggest problem is the assembly, activeName require the user to manually update by additional events, if there is to take over another user, do not know to use in this case, the situation is not switched tab will appear. And then to see the internal components to achieve, and then come back to modify the code, it is clear that such a component failure. All the dirty work by principle component implementation, the ideal state should be the user does not need to manage activeName, but to update the internal components.

How to improve

Modify prop?

Some may think, as we have to, that modify the value prop in the internal management of the internal components is not it? This approach look at the feasibility of
modifying the component tabChange method, the updated value of the prop when clicked

tabChange(item){
  this.activeName = item
  this.$emit('tabChange',item)
}

In use, the console throw warning

Since prop unidirectional data flow, the parent will be updated prop flows down to the sub-assembly, directly opposite the interior subassembly update state, will lead to the flow of data is not clear. For example, how in the parent component sub-assemblies depend same property, one of the sub-assemblies to update the property, will lead to a change in the rest of sub-assemblies, not easy to find if a problem occurs, and therefore is not recommended Vue us to do so. In addition, when the parent component is updated, prop subassemblies will be refreshed to the latest value.
Way data flow: https://cn.vuejs.org/v2/guide/components-props.html#%E5%8D%95%E5%90%91%E6%95%B0%E6%8D%AE% E6% B5% 81

Positive solutions: model options

Improved components

Component model options

And allowing a custom event prop when using v-model custom components. By default, a v-model on the assembly will be used as prop and the input value as Event, but some types of input, such as buttons and check boxes may want to use a different value to achieve the object of the prop. Use model option to avoid conflict generated by these circumstances.

model: https://cn.vuejs.org/v2/api/#model

Options in the model, we can bind a property, and add an event, you need only transfer value when calling the method to update the property.

<script>
export default {
  model:{
    prop: 'activeName',
    event: 'update'
  },
  props:{
    tabs:{
      type: Array,
      default: ()=> []
    },
    activeName:{
      type: String,
      default: ''
    }
  },
  methods:{
    tabChange(item){
      this.$emit('update',item) // 这里更新activeName
      this.$emit('tabChange',item)
    }
  }
}
</script>

Note that you still need to declare prop props in the component's options.

use

After using two-way binding components, attributes when the internal component updates, activeName parent component will be updated to use such components appear to be more elegant

<Tabs :tabs="tabs" v-model="activeName" />

Guess you like

Origin www.cnblogs.com/chanwahfung/p/12173902.html