Several communication nothing less than the following:
Prop
(Common)$emit
(More components for encapsulation).sync
Syntactic sugar (less)$attrs
&$listeners
(Component package with more)provide
&inject
(High-order component / component library with more)slot-scope
&v-slot
([email protected]+) newscopedSlots
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!
4 $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
andstyle
excluding). When a component does not declare any prop, where the binding will contain all the parent scope (class
andstyle
excluding), and can bev-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 canv-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
Andinject
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
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