Vue Learning Notes (3) Components
component is the core function of Vue.
<body> <div id="app"> <my-component :lists="lists"></my-component> </div> <div id="app1"> <my-component :lists="booksName"></my-component> </div> <script src="../vue.js"></script> <script> Vue.component('my-component', { props: ['lists'], template: '\ <ul>\ <li v-for="item in lists">\ {{item}}\ </li>\ </ul>' }); var app = new Vue({ el: '#app', data: { lists: ['Music', 'painting', 'Dance', 'motion'] } }) var app1 = new Vue({ el: '#app1', data: { booksName: ['Java Programming', 'C Language Programming', 'Python Program Design and Development'] } }) </script> </body>
1. Usage of components
Components are similar to Vue instances and need to be registered before they can be used.There are two ways to register: global registration and local registration.Once registered globally, any Vue instance can be used.
Vue.component('my-component', { props: ['lists'], template: '\ <ul>\ <li v-for="item in lists">\ {{item}}\ </li>\ </ul>' });
Among them, my-component is a registered component custom label name, which is recommended in the form of lowercase plus minus sign division.To use this component in a parent instance, you must register it before the instance is created, and then you can use it as <my-component></my-component>.
A template is the content of a component.The template's DOM structure must be contained by an element or it cannot be rendered.
Templates for Vue components are restricted by HTML in some cases, such as <table>which only allows <tr>, <td>, <th> table elements, so it is not valid to use components directly within <table>.In this case, a special is attribute can be used to mount the component.
<table> <tbody is="my-component" :lists="booksName"></tbody> </table>
tbody is replaced with the contents of the component when rendered.Common restriction elements are ul, ol, select, and, if using string templates, are unrestricted.
In addition to the template option, other options can be used in the component as in the Vue instance.Such as data, computed, methods, etc.However, when using data, slightly different from the instance, the data must be a function and then return the data.
Vue.component('my-component', { props: ['lists'], data: function() { return { myinfo: 'I am a message in a subcomponent' } }, template: '<div>\ <ul>\ <li v-for="item in lists">\ {{item}}\ </li>\ </ul>\ <p>{{myinfo}}</p>\ </div>' });
2. Use props to transfer data
1. Basic usage
Components not only reuse the content of templates, but also communicate among components.Typically, a parent component's template contains child components, which pass data or parameters forward to the child, and the child receives them to render different content or perform operations depending on the parameters.This forward transfer is done through props.
In a component, the option props is used to declare the data that needs to be received from the parent, and the value of porps can be divided into two types: a string array and an object, such as props: ['lists'] in the previous example, which uses an array.
The main difference between the data declared in props and the data return ed by the component data function is that the props are from the parent, while the data in data is the component's own data and the scope is the component itself, both of which can be used in template templates and computed computational properties and method methods.
<script> Vue.component('my-component', { props: ['lists', 'msg'], data: function() { return { info1: this.msg }; }, computed: { childinfo: function() { return this.msg + "111111"; } }, template: '<div>\ <ul>\ <li v-for="item in lists">\ {{item}}\ </li>\ </ul>\ <p>{{msg}}---{{info1}}---{{childinfo}}</p>\ </div>' }); var app = new Vue({ el: '#app', data: { lists: ['Music', 'painting', 'Dance', 'motion'], message: 'This is the first component' } }) var app1 = new Vue({ el: '#app1', data: { booksName: ['Java Programming', 'C Language Programming', 'Python Program Design and Development'], message: 'This is the second component' } }) </script>
The data msg in the above example is passed from the parent via props; info1 is passed from the props parent via return in component data; and childinfo is a property in component computed, in which msg data is passed from the parent via props is used.
Many times, the data passed from the parent is not written to death directly, but dynamic data from the parent. At this time, the command v-bind can be used to dynamically bind the value of props, and when the data of the parent component changes, it is also passed to the child component.
<div id="app"> <my-component :lists="lists" :msg="message"></my-component> </div> <div id="app1"> <table> <tbody is="my-component" :lists="booksName" :msg="message"></tbody> </table> </div>
In the example above, lists and: msg are dynamically bound parent data, where lists and msg must have the same name as the props array in the component.
2. One-way data flow
Business often encounters two situations where prop needs to be changed. One is when the parent component passes in the initial value, and the child component saves it as the initial value, allowing it to be used and modified at will within its own scope.In this case, another data can be declared within the component data, referencing the prop of the parent component.
Another is that Prop is passed in as the original value that needs to be transformed.In this case, you can just use the computed attribute.
Note: Objects and arrays in JS are reference types that point to the same memory space, so when props are objects and arrays, changes within child components affect parent components.
3. Data validation
Data validation is generally recommended when your components need to be made available to others. For example, a data must be of numeric type, and if a string is passed in, a warning pops up in the console.
<body> <script src="../vue.js"></script> <script> Vue.component('my-validator',{ props:{ //Must be a numeric type propA:Number, //Must be a string or number type propB:[String,Number], //Boolean value, if not defined, the default is true propC:{ type:Boolean, default:true }, //Numbers, and must be transmitted 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 []; } }, //Customize a validation function propF:{ validator:function(value){ return value>10; } } } }) </script> </body>
3. Component Communication
Component communication relationships can be divided into parent-child component communication, sibling component communication, and cross-level component communication.The parent and child communicate from the parent component to the child component and pass data through props.What about other communications?
1. Custom events (child components pass data to parent components)
Custom events are used when a child component needs to pass data to a parent component.In addition to listening for DOM events, v-on can also be used for custom events between components.
The parent component can use v-on directly on the child component's custom label to listen for custom events triggered by the child component
<body> <div id="app"> <h4>Data in parent component:{{info}}</h4> <my-component @increase="handleGetInfo"></my-component> </div> <script src="../vue.js"></script> <script> Vue.component('my-component', { template: '<button @click="changeFatherComponentData">Subcomponents pass data to parent components</button>', data: function() { return { childrenData: '' } }, methods: { changeFatherComponentData: function() { this.childrenData = "Subcomponents pass data to parent components"; this.$emit('increase', this.childrenData); } } }) var app = new Vue({ el: '#app', data: { info: 'Data in parent component' }, methods: { handleGetInfo: function(info) { this.info = info; } } }) </script> </body>
In the example above, the child component has a button that binds a method, changeFatherComponentData, in which the value of the child renData is first changed and then passed to the parent component through $emit, which is received by the v-on:increase, and the first parameter of the $emit() method is the name of the custom event, followed by data to be passed, which can be filled in or filled out moreYes.
2. Use v-model
<body> <div id="app"> <parent></parent> </div> <script src="../vue.js"></script> <script> Vue.component('child', { template: '<button @click="handleClick">Changing messages in parent components</button>', data: function() { return { childinfo: "This is a message in a subcomponent" } }, methods: { handleClick: function() { this.$emit('input', this.childinfo); } } }) Vue.component('parent', { template: '<div>{{parentinfo}}\ <child v-model="parentinfo"></child></div>', data: function() { return { parentinfo: "Messages in parent component" } } }) var app = new Vue({ el: '#app' }) </script> </body>
The event name of component $emit() is a special input when using v-model.
There are two requirements for implementing a bi-directional binding v-model component
- Receive a value property
- Trigger the input event when a new value exists
3. Non-parent-child component communication
<body> <div id="app"> <p>{{message}}</p> <component-a></component-a> <component-b></component-b> </div> <script src="../vue.js"></script> <script> var bus = new Vue(); Vue.component('component-a', { template: '<div><p>{{ainfo}}</p>\ <button @click="componenta">assembly a Click Event</button>\ </div>', data: function() { return { ainfo: 'assembly a Message' } }, methods: { componenta: function() { bus.$emit('on-message', 'assembly a Click Events in'); } }, mounted: function() { var _this = this; bus.$on('on-message', function(msg) { _this.ainfo = msg; }) } }) Vue.component('component-b', { template: '<button @click="componentb">assembly b Click Event</button>', methods: { componentb: function() { bus.$emit('on-message', 'assembly b Click Events in'); } } }) var app = new Vue({ el: '#app', data: { message: 'Messages in parent component' }, mounted: function() { var _this = this; bus.$on('on-message', function(msg) { _this.message = msg; }) } }) </script> </body>
First, create an empty Vue instance named bus with nothing in it; then define component-a and component-b globally; and finally create the Vue instance app, which listens for events on-message from bus in the life cycle mounted hook function when the app is initialized, whereas in component-a and component-b, clicking on the button will cause events on-mes via busSage sent out.At this point, the mounted functions of app and component-a receive events from bus.In this way, parent-child and sibling components communicate.
4. Index of parent and child components
In a child component, the parent instance or component of the component can be accessed directly by using this.$parent, or all its children can be accessed by this.$children, and infinitely up or down recursively until the root instance or the innermost component.
When there are many subcomponents, it is difficult to iterate through one instance of a component we need through this.$children.Especially when components are rendered dynamically, their sequence is irregular.Vue provides a way to index subcomponents by specifying an index name for them with a special property ref.
In the parent component template, the child component label specifies a name using ref and accesses the child component with the specified name within the parent component via this.$refs.
<body> <div id="app"> {{msg}} <button @click="handleClick">Change access to subcomponents through subcomponent index</button> <children ref="childrenA"></children> </div> <script src="../vue.js"></script> <script> Vue.component('children', { template: '<div>\ <p>{{message}}</p>\ </div>', data: function() { return { message: 'Content in subcomponents' } } }) var app = new Vue({ el: '#app', data: { msg: 'Content in parent group' }, methods: { handleClick: function() { this.$refs.childrenA.message = 'Change content in child components through parent components'; } } }) </script> </body>