component
Define the way
Global definitions
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
After global registration, any Vue instance can be used
Vue.component('my-component', {
template: '
here is the content of the component
'
})
// Vue proxies data and methods in methods
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
Local definition
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-component></my-component>
</div>
<script>
// Local registration is valid only in the instance scope
let child = {
template: '
here is the content of the component
'
}
// Vue proxies data and methods in methods
let app = new Vue({
el: '#app'.components: {
'my-component': child
}
})
</script>
</body>
</html>
Copy the code
Parent passes data to child: props
Use the option props to declare the data that needs to be received from the parent
Note: When props are objects and arrays, changes within a child component affect the parent component
Use is
The only table elements allowed in the table tag are , < TD >, , etc., so using components directly in the table tag is invalid. Components can be mounted using special IS properties.
-
< OL >
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<table>
<tbody is="my-component"></tbody>
</table>
</div>
<script>
// Local registration is valid only in the instance scope
let child = {
template: '
here is the content of the component
'
}
// Vue proxies data and methods in methods
let app = new Vue({
el: '#app'.components: {
'my-component': child
}
})
</script>
</body>
</html>
Copy the code
The props value is an array of strings
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<my-component warning-text="Data from parent component"></my-component>
</div>
<script>
Vue.component('my-component', {
// 1. Handle arrays
props: ['warningText'].template: '<div>{{warningText}}</div>'
})
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
The props data comes from the parent dynamic data
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="parentMessage">
<my-component :message="parentMessage"></my-component>
</div>
<script>
Vue.component('my-component', {
// 1. Handle arrays
props: ['message'].template: '<div>{{message}}</div>'
})
let app = new Vue({
el: '#app'.data: {
parentMessage: ' '}})</script>
</body>
</html>
Copy the code
Props and Computed work together
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<my-component :width="100"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component', {
// 1. Handle arrays
props: ['width'].template: '
Component contents
'.computed: {
style() {
return {
width: this.width + 'px'}}}})let app = new Vue({
el: '#app'
})
</script>
</body>
</html>
Copy the code
The data validation and props values are objects
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<my-component :width="100"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component', {
// 1. Process objects
props: {
// Must be a numeric type
propA: Number.// Must be a string or number type
propB: [String.Number].// Boolean, if not defined, the default is true
propC: {
type: Boolean.default: true
},
// Number, and must pass
propD: {
type: Number.required: true
},
// If it is an array or object, the default value must be a function to return
propE: {
type: Array.default: function() {
return[]}},// Define a validation function
propF: {
validator: function(value) {
return value > 10}}},template: '
Component contents
'.computed: {
style() {
return {
width: this.width + 'px'}}}})let app = new Vue({
el: '#app'
})
</script>
</body>
</html>
Copy the code
The sub-direction passes data to: $emit
$emit and $on
Middleman: It’s all dad
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Child1></Child1>
<! -- Event bus -->
<Child2></Child2>
</div>
<script>
Vue.component('Child1', {
template: '<div>Child1</div>'.mounted() {
this.$parent.$on('event-from-child2'.msg= > {
console.log('Child1:', msg); }); }}); Vue.component('Child2', {
template:
Child1: < button@click ="sendToChild1"> send message to Child1
.methods: {
sendToChild1() {
this.$parent.$emit('event-from-child2'.'some msg from child2')
}
},
})
Vue.component
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
$emit and v – on
A parent component can also use V-ON directly on the child component tag to listen for custom events triggered by the child component
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<p>{{total}}</p>
<my-component @increase="handleGetTotal" @reduce="handleGetTotal"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component', {
template: '\
\
\
\
'.data() {
return {
counter: 0}},methods: {
handleIncrease() {
this.counter++;
this.$emit('increase'.this.counter);
},
handleReduce() {
this.counter--;
this.$emit('reduce'.this.counter); }}})let app = new Vue({
el: '#app'.data: {
total: 0
},
methods: {
handleGetTotal(total) {
this.total = total
}
}
})
</script>
</body>
</html>
Copy the code
$emit and v – model
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<p>{{total}}</p>
<my-component v-model="total"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component', {
template: '<button @click="handleClick">+1</button>'.data() {
return {
counter: 0}},methods: {
handleClick() {
this.counter++;
this.$emit('input'.this.counter); }}})let app = new Vue({
el: '#app'.data: {
total: 0}})</script>
</body>
</html>
Copy the code
Is equivalent to
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<p>{{total}}</p>
<my-component @input="handleGetTotal"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component', {
template: '<button @click="handleClick">+1</button>'.data() {
return {
counter: 0}},methods: {
handleClick() {
this.counter++;
this.$emit('input'.this.counter); }}})let app = new Vue({
el: '#app'.data: {
total: 0
},
methods: {
handleGetTotal(total) {
this.total = total
}
},
})
</script>
</body>
</html>
Copy the code
V-model can create custom form input components for two-way data binding
Conditions that the child component needs to meet
- Receive a value attribute
- The input event is raised when a new value is present
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<p>{{total}}</p>
<my-component v-model="total"></my-component>
<button @click="handleReduce">- 1</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('my-component', {
template: '<input :value="value" @input="updateValue">'.props: ['value'].methods: {
updateValue(event) {
this.$emit('input', event.target.value)
}
},
})
let app = new Vue({
el: '#app'.data: {
total: 0
},
methods: {
handleReduce() {
this.total--; }}})</script>
</body>
</html>
Copy the code
Sibling or cross-level component communication:
bus
Using an empty Vue instance as a central event Bus
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Child1></Child1>
<! -- Event bus -->
<Child2></Child2>
</div>
<script>
// Event bus
Vue.prototype.$bus = new Vue()
Vue.component('Child1', {
template: '<div>Child1</div>'.mounted() {
this.$bus.$on('event-from-child2'.msg= > {
console.log('Child1:', msg); }); }}); Vue.component('Child2', {
template:
Child1: < button@click ="sendToChild1"> send message to Child1
.methods: {
sendToChild1() {
this.$bus.$emit('event-from-child2'.'some msg from child2')
}
},
})
Vue.component
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
Custom bus
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Child1></Child1>
<! -- Event bus -->
<Child2></Child2>
</div>
<script>
// Bus: event dispatch, listening, and callback management
class Bus {
constructor() {
this.callbacks = {}
}
$on(name, fn) {
this.callbacks[name] = this.callbacks[name] || []
this.callbacks[name].push(fn)
}
$emit(name, args) {
if (this.callbacks[name]) {
this.callbacks[name].forEach(cb= > cb(args))
}
}
}
// Event bus
Vue.prototype.$bus = new Bus()
Vue.component('Child1', {
template: '<div>Child1</div>'.mounted() {
this.$bus.$on('event-from-child2'.msg= > {
console.log('Child1:', msg); }); }}); Vue.component('Child2', {
template:
Child1: < button@click ="sendToChild1"> send message to Child1
.methods: {
sendToChild1() {
this.$bus.$emit('event-from-child2'.'some msg from child2')
}
},
})
Vue.component
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
$parent, $root, and $children
Use this.$parent to access the parent instance or component directly
In business, the child components should be as much as possible to avoid relying on the parent component data, more should not to take the initiative to modify its data, because it makes the father and son tightly coupled components, just look at the parent component, it is hard to understand the state of the parent component, because it can be any component changes, ideally, only the components you can modify its state. Parent and child components are best communicated through props and $emit
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
{{message}}
<my-component></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let bus = new Vue()
Vue.component('my-component', {
template: .methods: {
handleEvent() {
// After accessing the parent chain, you can do anything, such as modify the data directly
this.$parent.message = 'Content from component-a'}}})let app = new Vue({
el: '#app'.data: {
message: ' '}})</script>
</body>
</html>
Copy the code
Use this.$children to access all child components
Sub-component index: $refs
When there are many child components, it is difficult for $children to traverse, especially when the components are dynamically rendered and the sequence is not fixed. Use ref to specify the index name
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<button @click="handleRef">Get the child component instance through ref</button>
<my-component ref="comA"></my-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let bus = new Vue()
Vue.component('my-component', {
template: '
subcomponent
'.data() {
return {
message: 'Child component content'}}})let app = new Vue({
el: '#app'.methods: {
handleRef() {
// Access the specified instance through $refs
let msg = this.$refs.comA.message
console.log(msg); }}})</script>
</body>
</html>
Copy the code
Non-functions: $attrs, $Listeners
$attrs
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Child1></Child1>
<! -- Event bus -->
<Child2 msg="some message from parent"></Child2>
</div>
<script>
Vue.component('Child1', {
template: '<div>Child1</div>'.mounted() {
this.$parent.$on('event-from-child2'.msg= > {
console.log('Child1:', msg); }); }}); Vue.component('Child2', {
template:
Child2: {{$attrs. MSG}}< button@click ="sendToChild1">
'.methods: {
sendToChild1() {
this.$parent.$emit('event-from-child2'.'some msg from child2')
}
},
})
Vue.component
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
Grandparent component communication
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Parent msg="some message from grandpa"></Parent>
</div>
<script></script>
</body>
</html>
Copy the code
$listeners
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Parent msg="some message from grandpa" @foo="onFoo"></Parent>
</div>
<script>
Vue.component('Parent', {
template: '< div > Parent: < Child2 v - bind = "$attrs" v - on = "$listeners" > < / Child2 > < / div >'}); Vue.component('Child2', {
template:
Child2: {{$attrs. MSG}}< button@click ="sendToChild1">
'.methods: {
sendToChild1() {
this.$emit('foo')}}})let app = new Vue({
el: '#app'.methods: {
onFoo() {
console.log('msg from child2'); }}})</script>
</body>
</html>
Copy the code
Inter-layer parameter transmission: provide/inject
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<Parent msg="some message from grandpa" @foo="onFoo"></Parent>
</div>
<script>
Vue.component('Parent', {
template: '< div > Parent: < Child2 v - bind = "$attrs" v - on = "$listeners" > < / Child2 > < / div >'}); Vue.component('Child2', {
template: '< div > Child2: < div > < / div > {{bar}} {{$attrs. MSG}} < button @ click = "sendToChild1" > send a message to child1 < / button > < / div >'.inject: ['bar'].methods: {
sendToChild1() {
this.$emit('foo')}}})let app = new Vue({
el: '#app'.methods: {
onFoo() {
console.log('msg from child2'); }},provide() {
return {
bar: 'bar'}}})</script>
</body>
</html>
Copy the code
Distribution content: slot
A single slot.
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component>
<p>Content of distribution</p>
<p>More content for distribution</p>
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script></script>
</body>
</html>
Copy the code
A named slot.
Distributes content to the location specified by the child component
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component>
<h2 slot="header">The title</h2>
<p>Body content</p>
<p>More text content</p>
<div slot="footer">At the bottom of the information</div>
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script></script>
</body>
</html>
Copy the code
Scope slot
The distribution of content takes into account the data usage scenarios in the child component: the slot of the child component can be reused or the slot content can be inconsistent
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component>
<template scope="props">
<p>Content from the parent component</p>
<p>{{props.msg}}</p>
</template>
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script></script>
</body>
</html>
Copy the code
Access slot: $slots
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component>
<h2 slot="header">The title</h2>
<p>Body content</p>
<p>More text content</p>
<div slot="footer">At the bottom of the information</div>
</child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script></script>
</body>
</html>
Copy the code
Advanced usage of components
Recursive components
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component :count="1"></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('child-component', {
name: 'child-component'.props: {
count: {
type: Number.default: 1}},template: '\
\ 123\
\
\>
'
})
let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
Dynamic components
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<component :is="currentView"></component>
<button @click="handleChangeView('A')">Switch to A</button>
<button @click="handleChangeView('B')">Switch to the B</button>
<button @click="handleChangeView('C')">Switch to the C</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app'.components: {
comA: {
template: '< div > component A < / div >'
},
comB: {
template: '< div > component B < / div >'
},
comC: {
template: '< div > component C < / div >'}},data: {
currentView: 'comA'
},
methods: {
handleChangeView(component) {
this.currentView = 'com' + component
}
},
})
</script>
</body>
</html>
Copy the code
Asynchronous components
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<child-component></child-component>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('child-component'.function(resolve, reject) {
window.setTimeout(function() {
resolve({
template: '
I'm rendering asynchronously
'})},2000)})let app = new Vue({
el: '#app',})</script>
</body>
</html>
Copy the code
other
$nextTick
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="app">
<div id="div" v-if="showDiv">This is a text</div>
<button @click="getText">Get div content</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let app = new Vue({
el: '#app'.data: {
showDiv: false
},
methods: {
getText() {
this.showDiv = true;
this.$nextTick(function() {
let text = document.getElementById('div').innerHTML
console.log(text); })}}})</script>
</body>
</html>
Copy the code
Use extend and $mount
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Vue sample</title>
</head>
<body>
<div id="mount-div">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
// Manually mount the instance
var MyComponent = Vue.extend({
template: '<div>Hello: {{ name }}</div>'.data() {
return {
name: 'Aresn'}}})new MyComponent().$mount('#mount-div')
</script>
</body>
</html>
Copy the code