The upper good is like water, and water benefits all things without dispute. — Tao Te Ching

Introduction to the

In daily development, we often use some parent-child component communication, such as props and VUex, etc. In this document, we record how to use the other three methods, v-model and sync, and how to implement them. In fact, V-model and sync are synthetics. There is also $attrs, $listener to implement parent-child component communication.

use

v-model

2.2.0 + added

V-mode1 is essentially a syntax-candy that by default makes use of props named value and an event named input, but types of input like checkboxes, checkboxes, and so on might use the value feature for different purposes.

The v-model is used when a child component needs to change the value passed by the parent component through props

The parent component

  • The parent component passesv-modelBinding values
  • If you need according to thev-modelIncoming values change while triggering other updates please passwatchThe value of the incoming

Child components

  • The statementmodelObject setting eventeventandpropfield
  • throughporpsAccepts values passed by the parent component
  • Modification is done throughthis.$emitBroadcast events

Code examples:

Parent component code

<template>
  <children v-model="message"></children>
</template>
<script>
import children from "./children.vue";
export default {
  components: {
    children
  },
  data() {
    return {
      message: "parent"
    };
  },
  watch: {
    // Listen for message changes
    message(newV, oldV) {
      console.log(newV, oldV); }}};</script>

Copy the code

Subcomponent code

<template>
  <h1>{{ message }}</h1>
</template>
<script>
export default {
  model: {
    prop: "message".// This field refers to the MSG that the parent component passes to the child component when setting the V-model
    event: "input" // This field indicates that the parent component listens for parent-event events
  },
  props: {
    message: String // The same props as the Prop of the model must be defined here, because the V-Model will pass values to the child components
  },
  mounted() {
    // The MSG is sent asynchronously to the parent component v-model to achieve bidirectional control
    setTimeout(_= > {
      this.$emit("input"."children");
      // Emit this value to trigger parent-event, passing some to the v-model bound variable of the parent component
    }, 1500); }};</script>

Copy the code

The above example is implemented using the V-Model, and the following does not.

No V-Model implementation is used

A code example is as follows:

Parent component code modification

<template>
  <Children :message="message" @input="(event) => { message = event }"/>
</template>
<script>
/ / the same
</script>

Copy the code

Child component code modification

<template>/ / the same</template>
<script>
export default {
  props: {
    message: String
  },
  mounted() {
    setTimeout((a)= > {
      this.$emit("input"."children");
    }, 1500); }};</script>

Copy the code

Just split the V-Model into props and @input events. The child component doesn’t need to configure the Model, just accept the props and broadcast the event via this.$emit. Of course, this method is relatively simple compared with the V-Model method, but the flexibility of checking a lot, choose to use which depends on personal preference. Online Address:

Can’t put iframe can only put a link to this code example

sync

2.3.0 + added

In some cases, we may need to “bidirectional bind” a prop. Unfortunately, true bidirectional binding ** creates maintenance problems, because child components can modify the parent with no obvious source of change in either parent or child.

This is why we recommend replacing the schema triggering event with update:myPropName. This can also be done with the sync modifier.

Based on the above code, the general modification is as follows:

The parent component

  • Trigger events by modifying theminputforupdate:myPropNameAchieve the same effect

Child components

  • By modifying thethis.$emit(update:myPropName)

The code is as follows:

Parent component code modification

  // Modify as follows
  <Children :message="message" @update:input="(event) => { message = event }"/>
Copy the code

Child component code modification

  // Nothing else
  this.$emit("update:input"."children");
Copy the code

Sync implementation

The above code can be abbreviated to sync as follows:

Parent component code modification

  // Modify as follows
  <Children :messag.sync="message"/>
Copy the code

Child component code modification

  // Nothing else
  this.$emit("update:messag"."children");
Copy the code

Sync also supports objects, which can be abbreviated to v-bind, but note the following two objects:

Note that v-bind with the.sync modifier cannot be used with expressions (e.g. V-bind :title.sync= “doc.title + ‘! ‘” is invalid). Instead, you can only provide the name of the property you want to bind, similar to the V-Model. Using v-bind.sync on a literal object, such as v-bind.sync= “{title: doc.title}”, does not work because there are many edge cases to consider when parsing a complex expression like this.

listeners

$attrs

2.4.0 new

  • Type:{ [key: string]: string }
  • read-only
  • Detail: contains non-action in parent scopepropIdentified (and captured) feature bindings (classstyleExcept). When a component does not declare anypropThis contains all the bindings of the parent scope (classstyleExcept), and can passv-bind="$attrs"Pass in internal components – useful when creating high-level components.

$listeners

2.4.0 new

  • Type:{ [key: string]: Function | Array<Function> }
  • read-only
  • Detail: contains the parent scope (excluding.nativeModifier of)v-onEvent listeners. It can go throughv-on="$listeners"Passing in internal components – useful when creating higher-level components.

Realization of communication

Realize parent-child component communication

Parent component code

<template>
  <div class="parent">
    <Children
      :message="message"
      @upDate="upDate"
      type="del"
      @input="(event) => { message = event }"
    />
  </div>
</template>

<script>
import Children from "./Children";
export default {
  components: {
    Children
  },
  data() {
    return {
      message: "parent".type: "del"
    };
  },
  methods: {
    upDate (event) {
      console.log(event);
      this.type = event; }},watch: {
    message: function() {
      console.log("Update message value to" + this.message); }}};</script>
Copy the code

Subcomponent code

<template>
  <div v-bind="$attrs" v-on="$listeners" class="children">{{message}} <span @click="$listeners.upDate('data')">{{$attrs.type}}</span></div>
</template>

<script>
export default {
  props: {
    message: String
  },
  mounted() {
    // console.log(this.$attrs);
    // console.log(this.$listeners);
    setTimeout((a)= > {
      this.$emit("input"."children");
      this.$emit('upDate'.'add')},1500); }};</script>
Copy the code

Note $listeners and $attrs can be transmitted across domains, similar to context in React, but with some of the same design concepts.

conclusion

Sync modifier is detected, and multiple props are compiled to generate multiple events during the Complier phase. In fact, directives like this, modifiers, and custom directives are all compiled in VUE and parsed into code that V8 can execute.

Whether it is Vue, Babel or React, the compile phase of complier can be divided into three stages:

  • By lexical analysisparseGenerate abstractASTorAbstract code tree
  • To optimize theAST, such asvueMark static nodes,babalThe phase of extracting static code is calledoptimizeorOptimize the AST tree
  • inASTThe code phase, which generates executable code, can be calledcodegen

Both V-Model and sync can communicate with parent components and modify the values passed by the parent component in the child component. In the usual view of the approach can be used in these two ways, the specific choice of that way to see personal preferences. Related attributes are also used in the element-UI input component.

reference

$attrs

-v model for customizing components

Sync – modifier