I. Using Components
1. Registration
Create a Vue instance:
new Vue({
el: '#some-element',
// option
})
To register a global component, you can use Vue.component(tagName,options)
Vue.component('my-component', {
// option
})
Use w3c rules (lowercase, with a short bar) as much as possible for custom tag names.
After the component is registered, it can be used as a custom element in the module of the parent instance. Make sure that components are registered before initializing the root instance:
<div id="example">
<my-component></my-component>
</div>
// register
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// Create a root instance
new Vue({
el: '#example'
})
2. Local registration
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
// ...
components: {
// < my-component > will only be available in the parent template
'my-component': Child
}
})
3.DOM template parsing instructions
When using DOM as a template, there are some limitations of HTML. Such as:
<table>
<my-row>...</my-row>
</table>
The alternative is to use special is attributes:
<table>
<tr is="my-row"></tr>
</table>
But if used
Components
In Vue.js, the relationship between parent and child components can be summarized as props down, events up. The parent component passes data down to the child component through props, and the child component sends messages to the parent component through events.
III. Prop
1. Transfer data using Prop
The scope of component instances is isolated. This means that data from the parent component cannot (and should not) be directly referenced within the template of the child component. To make the child component use the data of the parent component, you need to pass the props option of the child component.
Vue.component('child', {
// Declare props
props: ['message'],
// Like data, prop can be used in templates
// It can also be used in vm instances like "this.message"
template: '<span>{{ message }}</span>'
})
This passes in a common string:
<child message="hello!"></child>
2.camelCase VS kebab-case
Vue.component('child', {
// camelCase in JavaScript
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
<!-- kebab-case in HTML -->
<child my-message="hello!"></child>
Note that HTML is case-insensitive here, so instead of using a string template, you need to convert prop to kebab-case.
3. Dynamic Prop
<div>
<input v-model="parentMsg">
<br>
<child v-bind:my-message="parentMsg"></child>
</div>
The abbreviation syntax using v-bind is usually simpler:
<child :my-message="parentMsg"></child>
4. Literary Quantity Grammar vs Dynamic Grammar
<! -- Passes a string "1" -->. <comp some-prop="1"></comp>
It is incorrect to use literal grammar to pass values here, which are string 1 instead of number. To pass an actual number, you need to use v-bind.
<! - Pass the actual number - > <comp v-bind:some-prop="1"></comp>
5. Unidirectional Data Flow
prop is unidirectionally bound, and when the attributes of the parent component change, it is transmitted to the child component, but not vice versa.
In addition, every time the parent component is updated, all props of the child component are updated to the latest value. This means that prop should not be changed within subcomponents.
6.Prop verification
Vue.component('example', {
props: {
// Basic type detection (`null'means any type can be)
propA: Number,
// Various types
propB: [String, Number],
// Necessary and String
propC: {
type: String,
required: true
},
// Numbers, with default values
propD: {
type: Number,
default: 100
},
// The default value of an array/object should be returned by a factory function
propE: {
type: Object,
default: function () {
return { message: 'hello' }
}
},
// Custom Validation Function
propF: {
validator: function (value) {
return value > 10
}
}
}
})
type can be the following native constructor:
- String
- Number
- Boolean
- Function
- Object
- Array
IV. Custom Events
1. Binding custom events with v-on
Each Vue instance implements an Events interface, that is:
- Use $on(eventName) to listen for events
- Use $emit(eventName) to trigger events
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter', {
template: '<button v-on:click="increment">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
increment: function () {
this.counter += 1
this.$emit('increment')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
2. Binding native events to components
<my-component v-on:click.native="doTheThing"></my-component>
3. sync modifier
The value of the child component is synchronized to the parent component.
<comp :foo.sync="bar"></comp>
It will be expanded to:
<comp :foo="bar" @update:foo="val => bar = val"></comp>
When a subcomponent needs to update the foo value, it needs to explicitly trigger an update event:
this.$emit('update:foo', newValue)
4. Form input components using custom events
<currency-input v-model="price"></currency-input>
Vue.component('currency-input', {
template: '\
<span>\
$\
<input\
ref="input"\
v-bind:value="value"\
v-on:input="updateValue($event.target.value)"\
>\
</span>\
',
props: ['value'],
methods: {
// Instead of updating values directly, this method is used to format and limit the number of digits of input values.
updateValue: function (value) {
var formattedValue = value
// Delete space characters on both sides
.trim()
// Keep 2 decimal places
.slice(0, value.indexOf('.') + 3)
// If the values are not uniform, manual coverage is used to maintain consistency
if (formattedValue !== value) {
this.$refs.input.value = formattedValue
}
// Emit values through input events
this.$emit('input', Number(formattedValue))
}
}
})
5. Non-parent-child component communication
Sometimes two components also need to communicate (non-parent-child relationship). In a simple scenario, an empty Vue instance can be used as the central event bus:
var bus = new Vue()
// Triggering events in component A
bus.$emit('id-selected', 1)
// Listen for events in hooks created by component B
bus.$on('id-selected', function (id) {
// ...
})
5. Distribution of content using Slot
<child-component>
{{ message }}
</child-component>
Vue.component('child-component', {
// Effective, because it's in the right scope
template: '<div v-show="someChildProperty">Child</div>',
data: function () {
return {
someChildProperty: true
}
}
})
1. Single Slot
Unless the child component template contains at least one socket, the content of the parent component will be discarded. When the child component template has only one slot without attributes, the entire content fragment of the parent component will be inserted into the DOM location where the slot is located, and the slot tag itself will be replaced.
Initially, everything in the tag was considered standby. The standby content is compiled within the scope of the child component and displayed only when the host element is empty and there is no content to insert.
2. Named Slot
Elements can use a special attribute name to configure how to distribute content. Multiple slots can have different names. Named slots match elements with slot characteristics in content fragments.
You can still have an anonymous slot, which is the default slot, as an alternate slot for content fragments that cannot be matched. If there is no default slot, the content fragments that cannot be matched will be discarded.
3. Scope slots
Scope slots are special types of slots used to replace rendered elements with a reusable template that can transfer data to them.
VI. Dynamic Components
By using retained elements and dynamically binding to its is feature, we enable multiple components to use the same mount point and switch dynamically.
keep-alive
If the switched component is kept in memory, its state can be preserved or re-rendering can be avoided. To do this, you can add a keep-alive instruction parameter
VII. Miscellaneous Matters
1. Writing reusable components
<my-component
:foo="baz"
:bar="qux"
@event-a="doThis"
@event-b="doThat"
>
<img slot="icon" src="...">
<p slot="main-text">Hello!</p>
</my-component>
2. Subcomponent Index
3. Asynchronous components
In large applications, we may need to split the application into several small modules and download it from the server on demand. To make things simpler, Vue. JS allows components to be defined as a factory function that dynamically parses component definitions. Vue.js triggers factory functions only when components need to be rendered, and caches the results for subsequent rendering.
4. Advanced Asynchronous Components
5. Component naming conventions
6. Recursive Components
Components can recursively call themselves in their templates, but only if they have the name option
7. Loop references between components
8. Inline template
If the subcomponent has an inline-template feature, the component will treat its content as a template rather than as a distribution content. This makes the template more flexible.
9.X-Templates
Another way to define templates is to use the text/x-template type in JavaScript tags and specify an id.
10. Use v-once for low-overhead static components
Although rendering HTML in Vue is fast, when there is a lot of static content in the component, you can consider using v-once to cache the rendering results, just like this:
Vue.component('terms-of-service', {
template: '\
<div v-once>\
<h1>Terms of Service</h1>\
... a lot of static content ...\
</div>\
'
})