0, Getting Started
Before officially explain the components, we first look at a simple example:
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<button-counter></button-counter>
</div>
<script>
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">{{ count }} times</button>'
})
new Vue({
el: '#app',
})
</script>
</body>
</html>
Let's take a closer look at the above code is this:
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">{{ count }} times</button>'
})
We first global method Vue.component()
creates a global component called the button-counter
The first method is a parameter of the component name, the second parameter is an option object, the object contains two attributes, data
andtemplate
Property data
is a function of target returns for dynamic data storage
The reason defined as a function, because the components may be used to create multiple instances, if defined as an object, all instances will share the same data objects
Property template
is a template string , HTML code that defines the component
It should be noted that the components must be a single root element , that is to say the content of the template must be wrapped within a parent element
new Vue({
el: '#app',
})
<div id="app">
<button-counter></button-counter>
</div>
Then, we can pass in a new Vue()
root instance created in this component as a custom elements use
Well, after a preliminary understanding of the components have, here we come to learn in detail
1, component registration
Examples of components are reusable Vue, before using the component, the component we must first be registered in order to be able to be identified Vue
(1) There are two component registration parameters, namely the component names and options object
- Component Name
Defined component name in two ways, namely kebab-case (separated by a dash named) and PascalCase (named after the first letter capitalized)
kebab-case: when referring to, also need to use the kebab-case
PascalCase: When you use the template, both nomenclature are available; when used in the DOM, only kebab-case is valid
- Options object
Options with the object received by new Vue()
the received option is similar, the only exception is as el
options such instances root-specific
(2) The component registration There are two ways, namely, global registration and local register
- Global registration
We can use the global method Vue.component()
globally registered, the first parameter of the method is the component name, the second parameter is the options object
Component global registration can be used in any instance root Vue newly created
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
new Vue({ el: '#app' })
- Local registration
We can use when creating a root instance option components
for local registration, it is an object, is the key component name, the value of the option is subject
Registered partial assembly can not be used in its subassembly, i.e., the following example two components can not call each other inside each
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
If you want ComponentA
in ComponentB
available, we will need to change a wording:
var ComponentA = { /* ... */ }
var ComponentB = {
components: {
'component-a': ComponentA
},
// ...
}
2, the data is transmitted to the sub-assembly - prop
prop some custom properties in the component registration, when a characteristic value is passed to a prop, it becomes an attribute of that component instance
(1) passes static prop
In the following example, we pass to prop up a static value,Title Here
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<title-item title="Title Here"></title-item>
</div>
<script>
Vue.component('title-item', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
new Vue({
el: '#app'
})
</script>
</body>
</html>
(2) deliver dynamic prop
In the following example, we passed v-bind
bind a dynamic object to the prop,content
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<title-item v-bind:title="content.title"></title-item>
</div>
<script>
Vue.component('title-item', {
props: ['title'],
template: '<h3>{{ title }}</h3>'
})
new Vue({
el: '#app',
data: {
content: {
'title': 'Title Here'
}
}
})
</script>
</body>
</html>
(. 3) and prop prop type validation
In the two examples above, props is an array of strings, each of which is a string prop
But in fact, prop may also be other types
Then we can list objects with prop, which is the name of the object key prop of the value of the object is of type prop
Vue.component('my-component', {
props: {
propA: String,
propB: Number,
propC: Boolean,
propD: Array,
propE: Object,
propF: Function
// ...
},
// ...
})
Since the prop with the type, it is necessary to determine whether the type of prop, we can customize the prop of authentication (The following is an example of an official document)
Vue.component('my-component', {
props: {
// 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
propA: Number,
// 多个可能的类型
propB: [String, Number],
// 必填的字符串
propC: {
type: String,
required: true
},
// 带有默认值的数字
propD: {
type: Number,
default: 100
},
// 带有默认值的对象
propE: {
type: Object,
// 对象或数组默认值必须从一个工厂函数获取
default: function () {
return { message: 'hello' }
}
},
// 自定义验证函数
propF: {
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ['success', 'warning', 'danger'].indexOf(value) !== -1
}
}
}
})
When prop verification fails, (development environment to build versions) Vue will generate a warning console
3, pass data to the parent component - Custom Event
prop is a unidirectional downlink binding, i.e. update the parent will flow down to prop the subassembly, but not vice versa
If sub-assemblies should pass the data to the parent component, you need to use custom events
Parent component can be v-on
any event listener sub-component instances, and sub-assemblies can $emit()
trigger events
(1) monitor sub-component events
<!DOCTYPE html>
<html>
<head>
<title>Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
<script>
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment')
}
},
})
new Vue({
el: '#app',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
</script>
</body>
</html>
Let's look at a detailed explanation of the code above:
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment')
}
},
})
First, we define a component called the button-counter
Subcomponents button-counter use v-on
listens native event click, the event handler isincrementHandler()
In incrementHandler()
, first (data subassemblies) counter value plus 1, then trigger a custom event increment
<div id="app">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
new Vue({
el: '#app',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
Also root component by v-on
listening custom event increment, the event handler isincrementTotal()
In incrementTotal()
, the value of total (root component in the data) plus 1
(2) throws a value by event
We can $emit()
throw a value of the second argument to the function in
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment', 2)
}
},
})
And receiving the value of the first parameter of the event handler
new Vue({
el: '#app',
data: {
total: 0
},
methods: {
incrementTotal: function (value) {
this.total += value
}
}
})