catalogue
1.4 value transfer between components
1, Vue components
1.1 overview
assembly (Component) is one of the most powerful functions of Vue.js. It is a polymer of html, css, JS, etc.
1.2. Global registration
Vue.component ('component name ', {})
The first parameter is the label name, and the second parameter is an option object.
After the global component is registered, any Vue instance can be used.
Component considerations:
- structure Most of the options passed in during Vue instance can be used in the component, with one exception: data Must be a function, and this function requires an object to be returned (because the object is a reference type)
- The component template must be a single root element
- The content of a component template can be a template string
<div id="app"> <!-- After the global component is registered, it is called directly --> <hello></hello> </div> <script> // Global component registration - defined once, available globally // In vue2.x, it is recommended that our components use lowercase (the initial letters are not case sensitive) // The component is a small hump name, username = > converted to lowercase = > user name // data must be a function that returns an object // Vue.component('name ', {configuration}) let cmp = Vue.component('hello', { data() { return { title: 'hello Global component' } }, // Template (string template) / render (close to the native json object) = > Vue it is a virtual dom(json object) // The input parameter in render is the h variable by default. It is built and replaced. After replacement, it does not support jsx // template: `<div>{{ title }}</div>` render(h) { return h( 'div', { attrs: { name: 'aaa' } }, [ h('h3', {}, this.title), h('h3', { on: { click: () => { console.log('click22222', this.title) } } }, '22222'), h('h3', {}, '3333'), ]) } }); const vm = new Vue({ el: '#app', data: { } }) </script>
1.3 partial registration
Its Vue can only be registered at the current time Used in an instance through a Vue instance / component instance option components registers components that are only available in their scope
1.4 value transfer between components
1.4.1. Value transfer from parent component to child component
- Parent component to attribute Bind values to child components in the form of
- Subcomponents by using properties props Receive (props) is one-way bound (read-only property): when the property of the parent component When changes occur, they will be transmitted to sub components, but not vice versa)
<div id="app"> <!-- The parent of the child component passes values to the child component through custom attributes --> <child :age="age" :setagefn="setagefn"></child> <!-- <child></child> --> </div> <script> // assembly const Child = { data() { return { title: 'I am a local component' } }, // props: one-way data flow. The modified data can only be modified through the parent component, and the child component is notified to update // props: defines the name and type of the attribute defined by the parent component to the child component // props object | array // The scheme of array is to use it for yourself // props: ['age'], // When encapsulating a common component, be sure to capitalize the object type props: { // age: Number age: { type: Number, // Multiple types = > union type // type: [Number, String], // This attribute must exist. true must be passed, and false can not be passed // required: true, // The default value is written directly for normal types, and callback functions are used for reference types default: 10, // Custom validator validator: (v) => { if (v >= 160) { return false } return true } }, user: { type: Object, /* default: () => { return { name: 'Zhang San '} } */ // Returns an object default: () => ({ name: 'Zhang San' }) }, setagefn: Function }, mounted() { // Use the function passed in by the parent component to modify the data this.setagefn(101) }, template: `<div>{{title}} --- {{age}} -- {{user.name}}</div>` } // Root component const vm = new Vue({ el: '#app', data: { age: 100 }, // key is the tag name used in html and the value component object components: { child: Child }, methods: { setagefn(arg) { this.age = arg } } }) </script>
1.4.2 value transfer from child component to parent component
<div id="app"> <child :age="age" @onsetage="setage"></child> </div> <script> // Subcomponents const Child = { data() { return { title: 'I am a local component' } }, props: { age: Number }, template: `<div @click="incr">{{title}} --- {{age}}</div>`, methods: { incr() { // props unidirectional data flow // this.$emit('name of custom event ', [... Parameter]) // Add a custom event to the current component this.$emit('onsetage', 10) } } } // Root component const vm = new Vue({ el: '#app', data: { age: 100 }, // key is the tag name used in html and the value component object components: { child: Child }, methods: { setage(num) { this.age += num } } }) </script>
1.4.3 event bus
Value transfer between non parent and child components or between components at more levels. Value transfer between components is managed through a separate event center in Vue.
- Establish a unified event center
const bus = new Vue( )
- The data party is passed and triggered by an event bus.$emit( Method name, passed data)
- Receiving data party, in the life cycle function, through bus.$on( Method name, [params] ) To monitor
- Destruction event, at the data receiving party, through Bus. $off (method name) Unable to listen to data after destruction
1.4.4,Ref
ref is used to register reference information for elements or child components. Reference information will be registered in the parent component $ refs object. If it is used on an ordinary DOM element, the reference points to the DOM element; if it is used on a child component, the reference points to the component instance
#On ordinary dom elements
<p ref="p">hello</p>
#On sub assembly
<child-comp ref="child"></child-comp>
#Call
this.$refs. Reference name
ref works in normal dom tags
ref works on custom components
8.4.5,parent / children / root
Gets a collection of parent or child component objects
<div id="app"> <h3>new Vue -- {{msg}}</h3> <app></app> </div> <script> const Child = { data() { return { msg: '' } }, mounted() { // Get the root component of the current component. The root component has only one new Vue // console.log(this.$root) this.$root.msg = 'I am child To modify your data' // Get an array // console.log(this.$root.$children) /* this.$root.$children.forEach(child => { if (child.msg) { child.msg = 'abc' } }) */ // The son gets the father this.$parent.msg = 'Sub to modify' }, template: `<div> <h3>I am Child</h3> </div>` } const App = { data() { return { msg: 'app' } }, components: { Child }, template: `<div> <h3>I am App -- {{msg}}</h3> <child></child> </div>` } // new Vue const vm = new Vue({ el: '#app', data: { msg: '' }, components: { App } }) </script>
1.4.6,provide / inject
Publishing and injection are generally used in component encapsulation
<div id="app"> <h3>new Vue -- {{msg}}</h3> <app></app> </div> <script> const Child = { // Inject published data inject: ['username', 'fn'], data() { return { msg: '' } }, mounted() { // console.log(this.fn) this.fn() }, template: `<div> <h3>I am Child -- {{username}}</h3> </div>` } const App = { data() { return { msg: 'app' } }, components: { Child }, template: `<div> <h3>I am App -- {{msg}}</h3> <child></child> </div>` } // new Vue const vm = new Vue({ el: '#app', // Publish a piece of data that is shared among the descendants /* provide: { username: 'Zhang San ' }, */ provide() { return { username: this.msg, fn: this.fn } }, data: { msg: 'Li Si' }, components: { App }, methods: { fn() { console.log('fn') } } }) </script>
1.4.7, $attrs and $listeners
$attrs accepts all attributes that are not set through props
$listeners is an event that accepts custom events from all parent components to child components. You didn't send it through $emit
<div id="app"> <h3>new Vue -- {{msg}}</h3> <app name='Zhang San' age='20' @fn="fn"></app> </div> <script> const Child = { // props: ['age'], data() { return { msg: '' } }, mounted() { console.log(this.$attrs) // console.log(this.$listeners) // this.$listeners.fn('123') }, template: `<div> <h3>I am Child</h3> </div>` } // App this component is equivalent to the Child component protective shell (high-order component -- high-order function) const App = { data() { return { msg: 'app', attrs: null } }, created() { // Deep replication this.attrs = { ...this.$attrs } if (this.attrs.age >= 20) this.attrs.age = 'secrecy' }, components: { Child }, methods: { fn(value) { console.log(value) } }, // < child name = 'Zhang San' age ='20 '@ FN = "FN" > < / child > // <child v-bind="$attrs"></child> template: `<div> <h3>I am App -- {{msg}}</h3> <child v-bind="attrs"></child> </div>` } // new Vue const vm = new Vue({ el: '#app', data: { msg: 'Li Si' }, components: { App }, }) </script>
1.5 dynamic components
By using reserved < The component > element is dynamically bound to its is feature, so that multiple components can use the same mount point and switch dynamically
<component v-bind:is="currentView"></component>
<script>
var vm = new Vue({
el: '#root',
data: {
currentView: 'home'
},
components: {
home,
posts
}
})
</script>
- keep-alive
If you keep the switched component in memory, you can keep its state or avoid re rendering.
<keep-alive>
<component :is="currentView"></component>
</keep-alive>
<script>
var vm = new Vue({
el: '#root',
data: {
currentView: 'posts'
},
components: {
home,
posts
}
})
</script>
<div id="app"> <!-- <button @click="tab=true">child1</button> <button @click="tab=false">child2</button> <hr> <child1 v-if="tab"></child1> <child2 v-if="!tab"></child2> --> <button @click="cmp='child1'">child1</button> <button @click="cmp='child2'">child2</button> <hr> <!-- keep-alive It can be used in [dynamic component] and [routing] to maintain the status of components(Cache current component) Specify the components that need to be cached include Specify components that do not need to be saved exclude Choose one of the following two configurations --> <keep-alive :include="['child1']"> <component :is="cmp"></component> </keep-alive> </div> <script> const Child1 = { name: 'child1', data() { return { username: '' } }, created() { console.log('child1 - created') }, // The life cycle of the two components used only when dynamic components are used and keep alive is used activated() { // The current dynamic component is activated console.log('activated') }, deactivated(){ console.log('deactivated') }, template: `<div> <h3>I am Child1</h3> <input type="text" v-model="username" /> </div>` } const Child2 = { name: 'child2', data() { return { username: '' } }, created() { console.log('child2 - created') }, template: `<div> <h3>I am Child2</h3> <input type="text" v-model="username" /> </div>` } const vm = new Vue({ el: '#app', data() { return { // tab: true cmp: 'child1' } }, components: { child1: Child1, child2: Child2 } }) </script>
2, Component slot
The biggest feature of components is reusability, and good use of slots can greatly improve the reusability of components
2.1. Single slot
When the child component template has only one slot without attributes, the entire content fragment passed in by the parent component will be inserted into the slot DOM position and replace the slot label itself.
2.2 named slot
Sometimes we need multiple slots to complete the corresponding data custom display.
One without The < slot > exit of name will have the implied name "default".
since Updated since 2.6.0. Obsolete use slot s
# Subcomponents <div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> </div> # Parent component <app-layout> // Old writing <h1 slot="header">Here may be a page title</h1> // neographism // V-slots can only be added on < template > // Abbreviation: V-slot: header = = #header <template v-slot:header> <h1>Here may be a page title</h1> </template> <p>A paragraph of the main content.</p> </app-layout>
2.3. Scope slot
A scope slot is a special type of slot used as a Reusable template (which can be passed data) to replace the rendered elements. In the sub component, just pass the data to the slot, just like you will prop is passed to the component
<div id="app"> <child :users='users'> <!-- vue2.6 before --> <!-- <h6 slot="action" slot-scope="row" @click="pdel(row)">Delete it</h6> --> <!-- vue2.6 after --> <!-- <template v-slot:action="row"> <h3 @click="pdel(row)">delete</h3> </template> --> <template #action="row"> <h3 @click="pdel(row)">delete</h3> </template> </child> </div> <script type="text/template" id="userhtml"> <div> <table width="600" border="1"> <tr> <th>ID</th> <th>full name</th> <th>operation</th> </tr> <tr v-for="(item,index) in users" :key="item.id"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td> <!-- adopt slot Data transmission, this slot Is a scope slot --> <slot name="action" :info="item"> <button @click="del(index)">delete</button> </slot> </td> </tr> </table> </div> </script> <script> const child = { props: ['users'], name: 'child', template: '#userhtml', methods: { del(index) { console.log(index) } } } const vm = new Vue({ el: '#app', data() { return { users: [ { id: 1, name: 'Zhang San' }, { id: 2, name: 'Li Si' }, { id: 3, name: 'Wang Wu' }, ] } }, components: { child }, methods: { pdel(row) { console.log(row.info) } } }) </script>