Learning notes:Component details
Component details
Components and Reuse
Vue components need to be registered before they can be used. There are two ways of registration: global registration and local registration.
Global registration
Vue.component('my-component', {});
To use this component in the parent instance, you must register before the instance is created and then use it<my-component></my-component>
To use components in the form of.
Vue.component('my-component', {
template: `<div>这是一个组件</div>`
});
template
The DOM structure of must be contained by an element, missing<div></div>
Can’t render and report an error.
In the Vue instance, thecomponents
Option can register components locally, and the registered components are only valid under the scope of the instance.
Can also be used in componentscomponents
Option to register components so that they can be nested.
var Child = {
template: `<div>局部注册组件的内容</div>`
};
new Vue({
el: '#app',
components: {
'my-component': Child
},
});
Templates for Vue components are limited by HTML under certain circumstances, such as<table>
The internal regulations only allow<tr>
、<td>
、<th>
Such as these table elements, so in<table>
Invalid when directly using components within.In this case, specialis
Property to mount the component.
<div id="app">
<table>
<tbody is="my-component"></tbody>
</table>
</div>
Vue.component('my-component', {
template: `<div>这里是组件内容</div>`
});
Common limiting elements are<ul>
、<ol>
、<select>
.
Except ..template
In addition to the options, other options can be used in the component like Vue instances, such asdata
、computed
、methods
Wait.
But in usedata
At that time,data
Must be a function and then transfer the datareturn
go out.
JavaScript objects are reference relationships ifreturn
The object of refers to an external object, then this object is shared and any modification will be synchronized.
Useprops
Transfer data
Components not only reuse the contents of templates, but also communicate with each other.
Usually, the template of the parent component contains subcomponents. The parent component will forward data or parameters to the subcomponents. The subcomponents will render different contents or perform operations according to different parameters. This process of transferring data forward passes throughprops
To achieve.
In the assembly, use optionsprops
Declare data that needs to be received from the parent.props
The value of can be two kinds, one isString arrayOne isObject.
<my-component message="来自父组件的数据"></my-component>
props: ['message'],
template: `<div>{{message}}</div>`,
props
Data and components declared indata
In functionreturn
The main difference is thatprops
The data of is from the parent, whiledata
In the is the component’s own data, scope is the component itself, the two kinds of data can be in the templatetemplate
And calculation attributescomputed
And methodsmethods
To be used in.
Because HTML features are not case sensitive, humps are named when DOM templates are usedprops
The name should be changed to a dash split name.
<my-component warning-text="提示信息"></my-component>
Sometimes, the data passed is not directly written to death, but is dynamic data from the parent, at which time instructions can be used.v-bind
Dynamic bindingprops
When the data of the parent component changes, the child component is also passed.
<div id="app">
<input type="text" v-model="parentMessage">
<my-component :message="parentMessage"></my-component>
</div>
props: ['message'],
template: `<div>{{message}}</div>`,
data: {
parentMessage: ''
}
For use herev-model
The data of the parent is boundparentMessage
, when any input through the input box, the subcomponent receivedprops["message"]
It also responds in real time and updates component templates.
Unidirectional data flow
Two kinds of changes are often encountered in the business.prop
One is that the parent component passes the initial value in and the child component saves it as the initial value, which can be used and modified at will under its own scope. This can be done in componentsdata
Within the declaration of a data, reference the parent component’sprop
.
<div id="app">
<my-component :init-count="1"></my-component>
</div>
Vue.component('my-component', {
props: ['initCount'],
template: `<div>{{count}}</div>`,
data() {
return {
count:this.initCount
}
}
});
Data is declared in the componentcount
That gets the from the parent component when the component is initializedinitCount
, then has nothing to do with it, only maintenancecount
In this way, direct operation can be avoided.initCount
.
Another situation isprop
As the original value that needs to be transformed, this case can be passed in by calculating the attribute.
<div id="app">
<my-component :width="100"></my-component>
</div>
Vue.component('my-component', {
props: ['width'],
template: `<div :style="style">组件内容</div>`,
computed: {
style: function () {
return {
width: this.width + 'px'
}
}
}
});
Because CSS is used to transfer width with units (px) and numerical calculation is generally without units, calculation attributes are uniformly used within components.
In JavaScript, when referring to an object and an array, the type points to the same memory space, so
props
When it is an object or an array, changes within the child component will affect the parent component.
Array validation
Whenprop
When verification is required, object writing is required.
Generally, when components need to be provided to others for use, data verification is recommended. For example, some data must be of numeric type. If a string is passed in, a warning will pop up in the console.
<p data-height=”565″ data-theme-id=”0″ data-slug-hash=”WywyjV” data-default-tab=”js” data-user=”whjin” data-embed-version=”2″ data-pen-title=”prop” class=”codepen”>See the Penpropby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
Verifiedtype
The type can be:
String
Number
Boolean
Object
Array
Function
type
It can also be a custom constructor that uses theinstanceof
Testing.
Component communication
Component relationships can be divided into parent component communication, sibling component communication, and cross-level component communication.
Custom event
Custom events are used when child components need to pass data to parent components.
v-on
In addition to listening for DOM events, it can also be used for custom events between components.
JavaScript Design Pattern-Observer Pattern Method;
dispatchEvent
addEventListener
For subcomponents of Vue components$emit()
To trigger the event, the parent component uses the$on()
To listen for sub-component events.
The parent component can also be used directly on the custom label of the child component.v-on
To listen for custom events triggered by subcomponents.
< pdata-height = “365” data-theme-id = “0” data-slug-hash = “zrwjkv” data-default-tab = “js, result” data-user = “whjin” data-embedded-version = “2” data-pen-title = “custom event” class=”codepen”>See the PenCustom eventby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
In changing the component’sdata "counter"
After, through$emit()
Then pass it to the parent component, which uses the@increase
And@reduce
.$emit()
The first parameter of the method is the name of the custom event.
In addition to usingv-on
In addition to listening for custom events on the component, you can also listen for DOM events, at which point you can use the.native
Modifier indicates a native event when listening, listening to the component’s root element.
<my-component @click:native="handleClick"></my-component>
Usev-model
Vue can be used on custom componentsv-model
Instructions.
<my-component v-model="total"></my-component>
Component$emit()
The event name of is specialinput
, which is using the parent of the component, does not exist in the<my-component>
Use on@input="handler"
, but directly usedv-model
One data boundtotal
.
<my-component @input="handleGetTotal"></my-component>
v-model
It can also be used to create custom form input components for data bidirectional binding.
< pdata-height = “365” data-theme-id = “0” data-slug-hash = “zaqjbq” data-default-tab = “html, result” data-user = “whjin” data-embedded-version = “2” data-pen-title = “v-model bidirectional binding” class=”codepen”>See the PenV-model bidirectional bindingby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
Implementation of such a two-way bindingv-model
Components must meet the following two requirements:
- Receive one
value
Attribute - There are new ones
value
Time triggerinput
Events
Non-parent-child component communication
In actual business, besides parent-child component communication, there are many scenarios of non-parent-child component communication. Generally, there are two types of non-parent-child components.Brother componentAndAcross multi-level components.
InVue 1.xIn the version, in addition to$emit()
The method also provides¥dispatch()
And$broadcast()
.
$dispatch()
It is used to distribute events to superiors. As long as it is its parent (one or more levels), it can be used in Vue instanceevents
Receive within options.
This instance is only valid in VUE version 1.x:
< pdata-height = “365” data-theme-id = “0” data-slug-hash = “pkyooy” data-default-tab = “html, result” data-user = “whjin” data-embedded-version = “2” data-pen-title = “dispatch dispatch dispatch event” class=”codepen”>See the PenDispatch dispatch eventby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
$broadcast()
It broadcasts events from the higher level to the lower level. The usage is exactly the same and the direction is opposite.
Once these two methods issue an event, any component can receive it. The principle of proximity will be followed, and bubbling will stop after the first receipt unless it returns.true
.
These methods have been abandoned in vue2.x.
In Vue 2.x, any empty Vue instance is recommended as the central event bus (bus
), which is an intermediary.
< pdata-height = “365” data-theme-id = “0” data-slug-hash = “dkmgvj” data-default-tab = “html, result” data-user = “whjin” data-embedded-version = “2” data-pen-title = “vue-bus event bus” class=”codepen”>See the PenVue-bus event busby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
First of all, we created a system calledbus
Empty Vue instance of; The components are then defined globallycomponent-a
; Finally, Vue instance is created.app
.
Inapp
During initialization, that is, during the life cyclemounted
The hook function is listening forbus
Events ofon-message
And in the assemblycomponent-a
, click on the button will passbus
Take an incidenton-message
Send it out. At this timeapp
You will receive information frombus
To complete its own business logic in the callback.
This method skillfully and lightly realizes the communication between any component, including father and son, brother and cross-level.
If used in depth, it can be expanded.bus
Instance, add to itdata
、methods
、computed
Such as options, these are all public.
It is very useful in business, especially in collaborative development, because it is often necessary to share some common information, such as the user’s login nickname, gender, email, etc., as well as the user’s authorization.token
Wait.
Just let thebus
Once obtained, any component can be used directly from it at any time, which is very practical in single page rich application (SPA).
In addition to the central event busbus
In addition, there are two methods to achieve communication between components: parent chain and child component index.
Parent chain
In the subassembly, use thethis.$parent
The parent instance or component of the component can be accessed directly, and the parent component can also be accessed through thethis.$children
Access all its subcomponents, and can recursively access up or down indefinitely until the root instance or innermost component.
<div id="app">
<p>{{message}}</p>
<component-a></component-a>
</div>
Vue.component('component-a', {
template: `<button @click="handleEvent">通过父链直接修改数据</button>`,
methods: {
handleEvent: function () {
this.$parent.message = '来自组件component-a的内容'
}
}
});
var app = new Vue({
el: '#app',
data: {
message: ''
}
});
Although Vue allows this operation, in business, subcomponents should avoid relying on the data of the parent component as much as possible, and should not actively modify its data, because this makes the parent-child component tightly coupled, only looking at the parent component, it is difficult to understand the state of the parent component, because it can be modified by any component, and ideally, only the component itself can modify its state.
Parent-child components are best passed throughprops
And$emit()
To communicate.
Subcomponent index
When there are many subcomponents, passthis.$children
It is difficult to traverse a required component instance, especially when components are rendered dynamically, their sequence is not fixed.
Vue provides a method for indexing subcomponents with special propertiesref
To specify an index name for the subcomponent.
<p data-height=”365″ data-theme-id=”0″ data-slug-hash=”dKMLXY” data-default-tab=”html, result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-$refs” class=”codepen”>See the Pen <a href=”https://codepen.io/whjin/pen/dKMLXY/”>Vue-$refs</a> by whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
In the parent component template, use on the child component labelref
Specify a name and pass within the parent componentthis.$refs
To access the subcomponent with the specified name.
$refs
Fill only after the component rendering is complete, and it is non-responsive. It is only used as an emergency plan to directly access subcomponents and should be avoided in templates or calculation properties$refs
.
Vue 2.x willv-el
Andv-ref
Merge intoref
Vue will automatically determine whether it is a normal label or a component.
Useslot
Distribute content
This is used when you need to combine components and mix the contents of the parent component with the templates of the child component.slot
This process is calledContent distribution.
-
<app>
The component does not know what its mount point will contain. The contents of the mount point are determined by<app>
Is determined by the parent component of the. -
<app>
The component most likely has its own template.
props
Transmitting data,events
Trigger events andslot
Content distribution constitutes the three API sources of Vue components, and the most complex components are also composed of these three parts.
action scope
Templates in parent component:
<child-component>
{{message}}
</child-component>
Heremessage
Just oneslot
However, it binds the data of the parent component, not the component<child-component>
The data of.
The contents of the parent component template are compiled within the scope of the parent component, while the contents of the child component template are compiled within the scope of the child component.
<div id="app">
<child-component v-modle="showChild"></child-component>
</div>
Vue.component('child-component', {
template: `<div>子组件1</div>`,
});
var app = new Vue({
el: '#app',
data: {
showChild: true
}
});
The state hereshowChild
Binding is the data of the parent component.
Bind data on subcomponents:
<div id="app">
<child-component></child-component>
</div>
Vue.component('child-component', {
template: `<div v-model="showChild">子组件</div>`,
data() {
return {
showChild: true
}
}
});
var app = new Vue({
el: '#app',
});
Therefore,slot
The content distributed is scoped on the parent component.
singleslot
Use special<slot>
Element can open a for this componentslot
(slot), in the parent component template, everything inserted in the child component label will replace the child component’s<slot>
The label and its contents.
<div id="app">
<child-component>
<p>分发的内容</p>
<p>更多分发的内容</p>
</child-component>
</div>
Vue.component('child-component', {
template: `
<div>
<slot>
<p>如果没有父组件插入内容,我将作为默认出现。</p>
</slot>
</div>
`,
});
var app = new Vue({
el: '#app',
});
Subassemblychild-component
Is defined in the template of<slot>
Element, and use a<p>
As the default content, it is not used in the parent component.slot
The default text will be rendered when the. If it is writtenslot
, it will replace the whole<slot>
.
Subassembly
<slot>
The scope of which is the subcomponent itself.
NamedSlot
to<slot>
Element specifies aname
After that, multiple contents can be distributed and named.slot
Can be associated with a singleslot
Coexistence.
<p data-height=”265″ data-theme-id=”0″ data-slug-hash=”RJRVQJ” data-default-tab=”html,result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-slot” class=”codepen”>See the PenVue-slotby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
Three are declared within the subassembly<slot>
Element, in which<div class="main">
Internal<slot>
Not usedname
Property, which will be the defaultslot
Appears, parent component is not in useslot
The elements and contents of the feature will appear here.
If no default anonymity is specifiedslot
The extra content in the parent component will be discarded.
When using components in combination, the content distribution API is crucial.
Scope slot
Scope slots are specialslot
To replace rendered elements with a reusable template.
<div id="app">
<child-component>
<template scope="props">
<p>来自父组件的内容</p>
<p>{{props.msg}}</p>
</template>
</child-component>
</div>
Vue.component('child-component', {
template: `
<div class="container">
<slot msg="来自子组件的内容"></slot>
</div>
`,
});
var app = new Vue({
el: '#app',
});
Templates for subcomponents, in<slot>
There is a similarity on the elementprops
Writing Method for Passing Data to Componentsmsg="xxx"
To pass data to the slot.
Used in parent component<template>
Element and has ascope="props"
The characteristics of, hereprops
Is a temporary variable.
template
Can be passed through temporary variablesprops
Access data from subcomponent slotsmsg
.
A more representative use case for scope slots is the list component, which allows the component to customize how each item in the list should be rendered.
<div id="app">
<my-list :book="books">
<!--作用域插槽也可以是具名的Slot-->
<template slot="book" scope="props">
<li>{{props.bookName}}</li>
</template>
</my-list>
</div>
Vue.component('my-list', {
props: {
books: {
type: Array,
default: function () {
return [];
}
}
},
template: `
<ul>
<slot name="book" v-for="book in books" :book-name="book.name"></slot>
</ul>
`,
});
Subassemblymy-list
Receive a from the parentprop
arraybooks
And put it in thename
Forbook
Theslot
Use onv-for
Instruction loops, exposing a variable at the same timebookName
.
The usage scenario of scope slot can reuse sub-componentsslot
, and can makeslot
The content is inconsistent.
Accessslot
Vue 2.x provides access toslot
Methods of distributing content$slots
.
<p data-height=”365″ data-theme-id=”0″ data-slug-hash=”vrKZew” data-default-tab=”html, result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-$slots” class=”codepen”>See the Pen <a href=”https://codepen.io/whjin/pen/vrKZew/”>Vue-$slots</a> by whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
via$slots
Can access a namedslot
,this.$slots.default
Including all those not included in the nameslot
The node in the.
Advanced usage of components
Recursive component
Set up componentsname
Option, a component can recursively call itself within its template.
<div id="app">
<child-component :count="1"></child-component>
</div>
Vue.component('child-component', {
name: 'child-component',
props: {
count: {
type: Number,
default: 1
}
},
template: `
<div class="child">
<child-component :count="count+1" v-if="count<3"></child-component>
</div>
`,
});
Recursive use of components can be used to develop independent components with unknown levels of shutdown, such as cascade selectors and tree controls.
Inline template
The templates for components are usually found intemplate
As defined in the option, Vue provides the function of an inline template, which is used for component labels when using components.inline-template
Feature, the component will use its content as a template instead of distributing it as content, which makes the template more flexible.
<p data-height=”265″ data-theme-id=”0″ data-slug-hash=”OEXjLb” data-default-tab=”html,result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-inline-template” class=”codepen”>See the PenVue-inline-templateby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
Data declared in the parent componentmessage
And subcomponentsmsg
, both of which can be rendered (if they have the same name, the data of the subcomponent is preferred).This is the disadvantage of inline templates, that is, the scope is difficult to understand. If it is not a very special scene, it is recommended not to use inline templates easily..
Dynamic component
Vue.js provides a special element<component>
For dynamically mounting different components, use theis
Property to select the components to mount.
<p data-height=”365″ data-theme-id=”0″ data-slug-hash=”zaBdyY” data-default-tab=”html,result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-component” class=”codepen”>See the PenVue-componentby whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
You can bind directly to component objects:
<div id="app">
<component :is="currentView"></component>
</div>
var Home = {
template: `<p>Welcome home!</p>`
};
var app = new Vue({
el: '#app',
data: {
currentView: Home
}
});
Asynchronous component
Vue.js allows a component to be defined as a factory function that dynamically parses the component.
Vue.js only triggers factory functions when components need to be rendered, and caches the results for later rendering again.
<div id="app">
<child-component></child-component>
</div>
Vue.component('child-component', function (resolve, reject) {
window.setTimeout(function () {
resolve({
template: `<div>我是异步渲染的!</div>`
})
}, 1000)
});
var app = new Vue({
el: '#app',
});
The factory function receives aresolve
Callback, called when a component definition downloaded from the server is received. You can also callreject(reason)
Indicates that the load failed.
Other
$nextTick
Asynchronous update queue
Vue does not directly update DOM when observing data changes, but opens a queue and buffers all data changes occurring in the same event cycle. Duplicate data is removed during buffering, thus avoiding unnecessary calculations and DOM operations. Then, in the next event cycletick
In, Vue flushes the queue and performs the actual (de-duplicated) work.
Vue will give priority to native browser environmentPromise.then
AndMutationObserver
, if they are not supported, they will be adoptedsetTimeout
Replace.
$nextTick
Is used to determine when DOM updates have been completed.
<p data-height=”365″ data-theme-id=”0″ data-slug-hash=”RJRjgm” data-default-tab=”html, result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-$nextTick” class=”codepen”>See the Pen <a href=”https://codepen.io/whjin/pen/RJRjgm/”>Vue-$nextTick</a> by whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
X-Templates
Vue provides another way to define templates in<script>
Used in labelstext/x-template
Type and specify oneid
, will thisid
Assigned totemplate
.
<div id="app">
<my-component></my-component>
<script type="text/x-template" id="my-component">
<div>这是组件的内容</div>
</script>
</div>
Vue.component('my-component', {
template: `#my-component`,
});
var app = new Vue({
el: '#app',
});
Mount the instance manually
In some very special cases, Vue instances need to be created dynamically. Vue providesVue.extend
And$mount
Two methods to mount an instance manually.
Vue.extend
It is the basic Vue constructor, creating a “subclass”, and the parameter is an object containing component options.
If the Vue instance is not received at the time of instantiationel
Option, it is in the “unmounted” state and has no DOM element associated with it. Can be used$mount
Manually mount an unmounted instance. This method returns the instance itself, so other instance methods can be called in a chain.
<p data-height=”265″ data-theme-id=”0″ data-slug-hash=”BVzmbL” data-default-tab=”html, result” data-user=”whjin” data-embed-version=”2″ data-pen-title=”Vue-$mount” class=”codepen”>See the Pen <a href=”https://codepen.io/whjin/pen/BVzmbL/”>Vue-$mount</a> by whjin (@whjin) onCodePen.</p>
<script async src=”https://static.codepen.io/ass …; ></script>
In addition to the above writing, there are two writing methods:
new MyComponent().$mount("#app");
new MyComponent({
el: '#app'
})
Manually mounting instances (components) is an extreme advanced usage that is rarely used in the business and may only be used when developing some complex independent components.