Vue communication module (Full Version)

Several communication nothing less than the following:

  • Prop(Common)
  • $emit (More components for encapsulation)
  • .syncSyntactic sugar (less)
  • $attrs& $listeners(Component package with more)
  • provide& inject(High-order component / component library with more)
  • slot-scope& v-slot([email protected]+) new
  • scopedSlots Attributes
  • Other means of communication

The following introduced one by one, the great God, please bypass.

1. Prop

English pronunciation: [prɒp]. This in our daily used very much in development. In simple terms, we can pass data to the sub-assembly by Prop . With a vivid metaphor, the data transfer between the components corresponding to the parent-child drain tube from top to bottom, can only flow from the top down, can not backflow. This is exactly Vue design of unidirectional data flow . And an opening between the adapter and the pipe conduit is Prop, so that water (data) to flow down. So much, look at the code:

<div id="app">
  <child :content="message"></child>
</div>
// Js
let Child = Vue.extend({
  template: '<h2>{{ content }}</h2>',
  props: {
    content: {
      type: String,
      default: () => { return 'from child' }
    }
  }
})

new Vue({
  el: '#app',
  data: {
    message: 'from parent'
  },
  components: {
    Child
  }
})

2. $emit

English pronunciation: [imɪt]. The official argument is that the trigger event on the current instance. Additional parameters are passed to the listener callback . I understand you do not know can not say to understand, to briefly look at the code it:

<div id="app">
  <my-button @greet="sayHi"></my-button>
</div>
let MyButton = Vue.extend({
  template: '<button @click="triggerClick">click</button>',
  data () {
    return {
      greeting: 'vue.js!'
    }
  },
  methods: {
    triggerClick () {
      this.$emit('greet', this.greeting)
    }
  }
})

new Vue({
  el: '#app',
  components: {
    MyButton
  },
  methods: {
    sayHi (val) {
      alert('Hi, ' + val) // 'Hi, vue.js!'
    }
  }
})

You can severely poke here to view Demo logic is roughly the sauce Shener:! When I click a button on the page, triggering components  MyButton listen to events on  greet, and the parameters passed to the callback function  sayHi . To put it plainly, when we subassemblies from  Emit before an event (distribution), the internal event queue are ahead in  the On (monitor) and listen to this event callback. In fact, this is equivalent to the following wording:

vm.$on('greet', function sayHi (val) {
  console.log('Hi, ' + val)
})
vm.$emit('greet', 'vue.js')
// => "Hi, vue.js"

3. .sync modifier

This guy has a two-way binding functionality exists in [email protected] time, namely sub-assemblies can modify the value of the parent component. Because it violates the one-way data flow design, so in [email protected] when they were blown away. But above [email protected]+ version reintroduced this  .sync  modifier. But this time it's just syntactic sugar exists as a compile-time. It will be extended to automatically update a parent component attribute v-on listener. It means we manually update the value of the parent component, so that the source data changes more obvious. Since the official introduction of the following passage:

In some cases, we may need a prop for a "two-way binding." Unfortunately, the real issue will bring two-way binding on maintenance, because the sub-assemblies can be modified parent component, and in the parent assemblies and subassemblies are no obvious source changes.

Now as a syntactic sugar, is certainly some kind of shorthand writing, and what kind of writing it, look at the code:

<text-document
  v-bind:title="doc.title"
  v-on:update:title="doc.title = $event">
</text-document>

So we can use  .sync syntactic sugar abbreviated as follows:

<text-document v-bind:title.sync="doc.title"></text-document>

If we want to achieve such an effect: to change the value of the sub-components in the text box at the same time changing the value of the parent component. How to do it?

<div id="app">
  <login :name.sync="userName"></login> {{ userName }}
</div>
let Login = Vue.extend({
  template: `
    <div class="input-group">
      <label>姓名:</label>
      <input v-model="text">
    </div>
  `,
  props: ['name'],
  data () {
    return {
      text: ''
    }
  },
  watch: {
    text (newVal) {
      this.$emit('update:name', newVal)
    }
  }
})

new Vue({
  el: '#app',
  data: {
    userName: ''
  },
  components: {
    Login
  }
})

You can severely poke here to view Demo underlined the focus of the code, there are these words!:

this.$emit('update:name', newVal)

Official syntax is: update:myPropName which  myPropName represents the value prop to be updated. Of course, if you do not use the above .sync syntactic sugar. $ Emit can achieve the same effect. That's it!

$attrs and $listeners

  • The official website of the  $attrs explanation is as follows:

Comprising the parent scope not recognized (and obtain) the binding properties as a prop ( class and  style excluding). When a component does not declare any prop, where the binding will contain all the parent scope ( class and  style excluding), and can be  v-bind="$attrs" passed internal components - very useful when creating high-level components.

  • The official website of the  $listeners explanation is as follows:

The scope includes the parent (excluding  .native decorator)  v-on event listener. It can  v-on="$listeners" pass the internal components - very useful when creating a higher level of assembly.

I feel  $attrs and  $listeners attributes like two storage box, a property responsible for receiving, storing a responsible event, are in the form of an object to hold the data. Look at the following code explanation:

<div id="app">
  <child 
    :foo="foo" 
    :bar="bar"
    @one.native="triggerOne"
    @two="triggerTwo">
  </child>
</div>

As can be seen in Html, there are two properties and two methods, the difference between a property is  prop declared, the event is a  .native decorator.

let Child = Vue.extend({
  template: '<h2>{{ foo }}</h2>',
  props: ['foo'],
  created () {
    console.log(this.$attrs, this.$listeners)
    // -> {bar: "parent bar"}
    // -> {two: fn}
    
    // 这里我们访问父组件中的 `triggerTwo` 方法
    this.$listeners.two()
    // -> 'two'
  }
})

new Vue({
  el: '#app',
  data: {
    foo: 'parent foo',
    bar: 'parent bar'
  },
  components: {
    Child
  },
  methods: {
    triggerOne () {
      alert('one')
    },
    triggerTwo () {
      alert('two')
    }
  }
})

You can severely poke here to view Demo! You can see, we can  $attrs and  $listeners data transfer, and call processing where needed, it is still very convenient. Of course, we can also pass  v-on="$listeners" a level down pass, children and grandchildren are also endless! Meanwhile, if the descendants of the Listeners $ method, reference may be transmitted by the source to $ EMIT method, this method can receive the source of the transmitted parameters of the offspring.

An episode!

When we are given a non-Prop statement on the component after the code will compile these attributes are treated as original properties, added to the native html tag, look like after the above code is compiled:

<h2 bar="parent bar">parent foo</h2>

This will be difficult to see, as well as burst something. How to get rid of? This is  inheritAttrs  useless property! Add this property to a component on the line, usually with the  $attrs use. Look at the code:

// Source 
the let Child = Vue.extend ({ 
  ... 
  inheritAttrs: to false , // defaults to true 
  ... 
})

Again compiled:

<h2>parent foo</h2>

5. provide / inject

It is CP, feeling very mysterious. Look at the official to  provide / inject  description:

provide And  inject mainly provides use cases for high-end plug-ins / component library. Not recommended for direct application code. And this option needs to be used together to allow an ancestor component inject a dependency to all future generations, regardless of how deep the component level, and in the upstream and downstream relations since the establishment of the time is always effective.

This option requires the use of together, in order to allow an ancestor component inject a dependency to all future generations, regardless of how deep the component level, and in the upstream and downstream relations since the establishment of the time is always effective. A word which encapsulates: ancestral components provided by the variable provider, and then injected through the assembly offspring variables inject.

provide / inject API mainly to solve the communication problem between the cross-level components, but its usage scenarios, mainly sub-assembly components to obtain higher status, between the cross-level components to establish a relationship of dependency injection and unsolicited.

Read the description a little muddle! Sentence summary is this: Your father a child everything to help you keep waiting for you to grow up with the young married woman you want to marry you buy a house you want to buy a car for as long as he will try to meet some of you.

Here is the code to explain this statement:

<div id="app">
  <son></son>
</div>
Son = the let Vue.extend ({ 
  Template: '<H2> Son </ H2>' , 
  Inject: { 
    House: { 
      default : 'no room' 
    }, 
    CAR: { 
      default : 'no car' 
    }, 
    Money: { 
      / / When grown up a bit of money though 
      // only for living expenses, to the parents need to 
      default : '¥ 4500' 
    } 
  }, 
  the Created () { 
    console.log ( the this .house, the this .car, the this .money)
     // - > 'house', 'car', '¥ 10000' 
  } 
}) 

new new Vue ({ 
  EL: '#app',
  Provide: { 
    House: 'house' , 
    CAR: 'car' , 
    Money: '¥ 10000' 
  }, 
  Components: { 
    Son 
  } 
})

You can severely poke here View Demo!

6. slot-scope & v-slot

About this way, I see the introduction of this article. Portal ->

7.  scopedSlots Properties

About this way, I see the introduction of this article. Portal ->

8. Other communicate

In addition to these five ways, in fact, there are:

  • EventBus
The idea is to declare a global Vue instance variables EventBus , all data communications, event listeners are stored on this variable. It can be read using Event Bus for inter-component communication Vue learn more. So that to achieve the data sharing between components, somewhat similar to Vuex . However, this approach only applies to a very small project, complex project or recommendation Vuex. Here is the simple code implementation of EventBus:
<div id="app">
  <child></child>
</div>
// global variables 
the let EventBus = new new Vue () 

// subassembly 
the let Child = Vue.extend ({ 
  Template: '<H2> Child </ H2>' , 
  Created () { 
    the console.log (EventBus.message) 
    // -> 'Hello' 
    . $ EventBus EMIT ( 'Received', 'Child from' ) 
  } 
}) 

new new Vue ({ 
  EL: '#app' , 
  Components: { 
    Child 
  }, 
  Created () { 
    // variables stored 
    EventBus.message = 'the Hello' // event listener 
    EventBus. $ on ( 'received' ,function (val) {
    
      console.log('received: '+ val)
      // -> 'received: from child'
    })
  }
})

You can severely poke here View Demo!

  • Vuex

Official recommendation, Vuex is a specially developed for Vue.js application state management.

  • $parent

Parent instance, if any, the current instance. Examples can be performed by accessing the data interaction between the parent, but seldom occurs modify the data in the parent component directly.

  • $root

Examples of the current root Vue component tree. If the current instance has no parent instance, which would be its own. It can be performed by accessing the data interaction between the root component, but will seldom occurs parent components modify the data directly.

  • broadcast / dispatch

It is the method [email protected], events are broadcast and event dispatcher. Although [email protected] inside deleted, but you can simulate these two methods. Can learn from Element realized. Sometimes still very useful, for example, when we developed the components of the tree and so on.


Author: gongph
link: https: //juejin.im/post/5bd18c72e51d455e3f6e4334

 

Guess you like

Origin www.cnblogs.com/momo798/p/11721818.html