Because of the epidemic, I guess most people are like me, staying at home and studying occasionally. Instead, I ran into a problem of how to manual a V-Model and learned from it.

Note: So in the child component, you can define the value to accept the value through props, and then fire the input event via $emit to pass the new value and modify it.Copy the code

With that in mind, let’s start implementing a custom V-Model

One, the simplest implementation method

First, the code for the parent component:

<template> <div class=""> <p>{{name}}</p> <son v-model="name"></son> <! -- equivalent to the following --> <! -- <son type="text" :value="name" @input="name= the value returned by the child component "> --> </div> </template> <script type="text/javascript"> import Son from './son' export default { name: "", data() { return { name:'ydw', } }, components: { Son } } </script>Copy the code

Then there is the code for the child components:

<template> <div class> <input type="text" :value="value" @input="$emit('input',$event.target.value)"> </div> </template>  <script type="text/javascript"> export default { name: "", props:{ value:{ type: String, defalut () return '' } } }, data() { return { } }, components: { } } </script>Copy the code

I added a comment to the parent component of the code line, in fact, is to help me understand, I wonder if there are any friends like me, the first time I looked at it did not know what it was doing? Haw.

Use watch and $emit implementation

It is similar to the previous one, except that the above one uses the function of the input event to pass the value to the parent component through the frequent firing of the input event. Instead, the process is changed to listen for the value change through the watch, and then trigger the function event through the input event, and submit the changed value to the parent component. Ok, I just need to modify the subcomponent as follows:

<template>
  <div class>
    <input type="text" :value="sonVal" @input="handleModel" />
  </div>
</template>

<script type="text/javascript">
export default {
  name: "",
  props: {
    value: {
      type: String,
      defalut() {
        return "";
      }
    }
  },
  data() {
    return {
      sonVal:this.value
    };
  },
  watch: {
    value(newval) {
      this.sonVal = newval
    }
  },
  methods:{
    handleModel(e){
        this.sonVal = e.target.value
        this.$emit('input',this.sonVal)
    }
  }
};
</script>
Copy the code

Listen for changes in props via watch and assign to sonVal defined by the child component itself, bound to the input. It then commits to the parent component using the input event trigger function.

3. Use the latest syntax, model attribute.

Originally, I did not know there was this attribute, but I found this attribute unconsciously when I searched about the implementation method of V-Model on the Internet. Check the official document as follows:

This property is used to bypass the name value defined for props.

To see how it is used, let’s first look at how the child component is modified:

<template> <div class> <input type="text" :value="val" @input="$emit('change',$event.target.value)" /> </div> </template> <script type="text/javascript"> export default { name: "", model:{ prop:'val', event:'change' }, props: { val: { type: String, defalut() { return ""; } } }, data() { return { }; }}; </script>Copy the code

Prop in the Model property is the name of the pass, and event is the name of the event, but again, the pass name in props must be the same as the name of the prop in the Model property. In fact, just compare the first method to see that vue has an extra model attribute for the name value to use.

Also, what does it look like to use Wacth with the new properties, again just changing the son component

<template>
  <div class>
    <input type="text" :value="sonVal" @input="handleModel" />
  </div>
</template>

<script type="text/javascript">
export default {
  name: "",
  model:{
    prop:'val',
    event:'change'
  },
  props: {
    val: {
      type: String,
      defalut() {
        return "";
      }
    }
  },
  data() {
    return {
      sonVal:this.val
    };
  },
  watch: {
    value(newval) {
      this.sonVal = newval
    }
  },
  methods:{
    handleModel(e){
        this.sonVal = e.target.value
        this.$emit('change',this.sonVal)
    }
  }
};
</script>
Copy the code

In fact, there is not much modification, just want to post it. Then I’ll write a v-Model by hand, and give me a thumbs up, thumbs up, thumbs up, thumbs up, thumbs up, thumbs up.

The divider

It’s been more than half a year since this article was published, and I recently wrapped elementUI with VUe2.0, which happened to be the old thing to use when wrapping forms.

Let’s start with my simple wrapper code:

<template> <div class="form-container"> <el-form :model="filterObject" label-position="left" :label-width="labelWidth" >  <el-row :gutter="10"> <el-col v-for="item in formData" :key="item.prop" :span="item.span || 8" > <el-form-item :label="item.label"> <el-input v-if="item.type === 'text'" v-model="filterObject[item.prop]" clearable :disabled="item.disabled || false" :placeholder="item.placeholder" ></el-input> <el-select v-if="item.type === 'select'"  v-model="filterObject[item.prop]" clearable :placeholder="item.placeholder" @change="handleChange" > <el-option v-for="sub in item.arr" :key="sub.value" :label="sub.label" :value="sub.value" ></el-option> </el-select> </el-form-item> </el-col> </el-row> </el-form> </div> </template> <script> export default { model: { prop: 'filterObject', event: 'change', }, props: { filterObject: { type: Object, default() { return {} }, }, labelWidth: { type: String, default: '80px', }, formData: { type: Array, default() { return [] }, }, }, data() { return {} }, methods: { handleChange() { console.log(this.filterObject) }, }, } </script>Copy the code

The idea is that the parent component can pass in an object and use the values outside of the parent component to perform operations, rather than getting the values through the child component exposure method. This can be done when wrapping the search component, exposing the search component outward. the reset method exposes the values in the child component. Encapsulated Search is similar to this form in that it is wrapped in the elementUI form form.

Here is the code for the parent component:

<template> <div class="home"> <HHform :formData="searchOptions" labelWidth="120px" v-model="filterObject" ></HHform> </div> </template> <script> import HHform from '@/components/HH-form' export default { name: 'Home', components: {HHform,}, data() {return {searchOptions: [{type: 'select', prop: 'status', label: 'status', span: 5, placeholder: 'please select' arr: [{value: "', label: 'all admissions consultants'}, {value: 1, the label:' normal recruit gu,}, {value: 2, the label: 'frozen recruit gu,},],}, {type:' select ', prop: 'region' label: ':', span: 5, placeholder: 'please select', arr: [],}, {type: 'text', prop: 'userName', SPAN: 8, label: 'placeholder ', placeholder:' select or enter search ',}, {type: 'text', prop: 'phone', label: 'phone number:', span: 5, placeholder: 'select or enter a search,},], filterObject: {},}}, the methods: {},}}, < / script >Copy the code

The code of the parent component is relatively simple and can be passed directly through the V-model. Here’s a demo.



This method is currently used to encapsulate form components. The parent component passes the value directly without requiring the child component to provide the method return value. When encapsulating the search component, the child component exposes the method to get the value. Why? Because the search must be exposed in the search and reset method, this time out on the line. After a few months, I finally used something, specially recorded, hoping to help you in the process of packaging components. You can like it or bookmark it.