Home >Web Front-end >JS Tutorial >Vue.js component usage and development example tutorial
Components
Components can extend HTML elements and encapsulate reusable code. At a high level, components are custom elements. The compiler of vue.js adds special functions to it. In some cases, components can also It is in the form of a native HTML element, extended with the is attribute.
Vue.js components can be understood as ViewModel classes with predefined behaviors. A component can predefine many options, but the core ones are the following:
Template (template): The template declares the mapping relationship between the data and the DOM that is ultimately displayed to the user.
Initial data (data): the initial data state of a component. For reusable components, this is usually private state.
Accepted external parameters (props): Data is transferred and shared between components through parameters. Parameters are bound one-way (top to bottom) by default, but can also be explicitly declared two-way.
Methods: Modification operations on data are generally performed within the methods of components. User input events and component methods can be bound through the v-on directive.
Lifecycle hooks: A component will trigger multiple lifecycle hook functions, such as created, attached, destroyed, etc. In these hook functions, we can encapsulate some custom logic. Compared with traditional MVC, it can be understood that the logic of the Controller is dispersed into these hook functions.
Private resources (assets): In Vue.js, user-defined instructions, filters, components, etc. are collectively called resources. Since globally registered resources can easily lead to naming conflicts, a component can declare its own private resources. Private resources can only be called by the component and its subcomponents.
In addition, components within the same component tree can also communicate through the built-in event API. Vue.js provides a complete API for defining, reusing and nesting components, allowing developers to use components to build the entire application interface like building blocks.
Components greatly improve the efficiency, maintainability and reusability of code.
Use component
Register
1. Create a component constructor:
var MyComponent = Vue.extend({ //选项 })
2. Use the constructor as a component and register it with Vue.component(tag,constructor):
Vue.component('my-component',MyComponent)
3. Use it in the module of the parent instance as a custom element b98f2d1b8b5d79f8c1b053de334aa7b5:
<div id = "example"> <my-component></my-component> </div>
Example:
<div id="example"> <my-component></my-component> </div> // 定义 var MyComponent = Vue.extend({ template: '<div>A custom component!</div>' }) // 注册 Vue.component('my-component', MyComponent) // 创建根实例 new Vue({ el: '#example' })
Rendered as:
<div id = "example"> <div>A custom component!</div> </div>
Component’s The template replaces the custom element, which only serves as a mount point. You can use the instance option replace to decide whether to replace.
Partial registration
Register with the instance option components. There is no need to register each component globally. The component can only be used in other components:
var Child = Vue.extend({ /* ... */ }) var Parent = Vue.extend({ template: '...', components: { // <my-component> 只能用在父组件模板内 'my-component': Child } })
This kind of encapsulation is also suitable for other resources, such as instructions, Filters and transitions.
Registration syntactic sugar
// 在一个步骤中扩展与注册 Vue.component('my-component', { template: '<div>A custom component!</div>' }) // 局部注册也可以这么做 var Parent = Vue.extend({ components: { 'my-component': { template: '<div>A custom component!</div>' } } })
Component option issue
Most options passed into the Vue constructor can also be used in Vue.extend(), except for data and el, if you simply use an object as the data option Passed to Vue.extend(), all instances will share the same data object, so we should use a function as the data option and let this function return a new object:
var MyComponent = Vue.extend({ data: function () { return { a: 1 } } })
Template parsing
Vue The template is a DOM template that uses the browser's native parser, so it must be a valid HTML fragment. Some HTML elements have restrictions on what elements can be placed in it. Common restrictions are:
a cannot contain other interactive elements. (Such as buttons, links)
ul and ol can only directly contain li
select can only contain option and optgroup
table can only directly contain thead, tbody, tfoot, tr, caption, col, colgroup
tr can only Including th and td directly
In practice, these restrictions can lead to unexpected results. Although it may work in simple cases, you cannot rely on the result of a custom component's expansion before the browser validates it. For example
750d7c37f87c44b67b1e945084b6bc455a07473c87748fb1bf73f23d45547ab8...4afa15d3069109ac30911f04c56f3338c3b6035d40e49dd3cf5dfe627a1d2a00 is not a valid template, even though the my-select component eventually expands to 221f08282418e2996498697df914ce4e...b38bcc2238ab4d1406940bf887819d23.
Another result is that custom tags (including custom elements and special tags, such as 8c05085041e56efcb85463966dd1cb7e, d477f9ce7bf77f53fbcf36bec1b69b7a, ec872302d9f7ec49547f9998f4be2186) cannot be used in ul, select, table, etc. that have restrictions on internal elements. within the label. Custom tags placed inside these elements will be lifted outside the element and render incorrectly.
For custom elements, the is attribute should be used:
f5d188ed2c074f8b944552db028f98a1
<tr is="my-component"></tr> </table> //<template> 不能用在 <table> 内,这时应使用 <tbody>,<table> 可以有多个 <tbody> <table> <tbody v-for="item in items"> <tr>Even row</tr> <tr>Odd row</tr> </tbody> </table>
Props
Use props to pass data
The scope of the component instance is isolated, you can use props to pass the array For child components, props is a field of component data that is expected to be passed down from the parent component. The child component needs to explicitly declare props with the props option:
Vue.component('child', { // 声明 props props: ['msg'], // prop 可以用在模板内 // 可以用 `this.msg` 设置 template: '<span>{{ msg }}</span>' })
and then pass it a normal string:
<child msg="hello!"></child>
Dynamic props
用v-bind绑定动态props到父组件的数据,每当父组件的数据变化时,也会传导给子组件:
<div> <input v-model="parentMsg"> <child v-bind:my-message="parentMsg"></child> //<child :my-message="parentMsg"></child> </div>
props绑定类型
prop默认是单向绑定,当父组件的属性变化时,将传导给子组件,但是反过来不会,这是为了防止子组件无意修改了父组件的状态,可以使用.sync或.once绑定修饰符显式地强制双向或单次绑定:
<!-- 默认为单向绑定 --> <child :msg="parentMsg"></child> <!-- 双向绑定 --> <child :msg.sync="parentMsg"></child> <!-- 单次绑定 --> <child :msg.once="parentMsg"></child>
如果 prop 是一个对象或数组,是按引用传递。在子组件内修改它会影响父组件的状态,不管是使用哪种绑定类型。
父子组件通信
父链
子组件可以用this.$parent访问它的父组件,根实例的后代可以用this.$root访问它,父组件有一个数组this.$children,包含它所有的子元素
自定义事件
Vue实例实现了一个自定义事件接口,用于在组件树中通信,这个事件系统独立于原生DOM事件,用法也不同,每一个Vue实例都是一个事件触发器:
使用 $on() 监听事件;
使用 $emit() 在它上面触发事件;
使用 $dispatch() 派发事件,事件沿着父链冒泡;
使用 $broadcast() 广播事件,事件向下传导给所有的后代。
不同于 DOM 事件,Vue 事件在冒泡过程中第一次触发回调之后自动停止冒泡,除非回调明确返回 true。
<!-- 子组件模板 --> <template id="child-template"> <input v-model="msg"> <button v-on:click="notify">Dispatch Event</button> </template> <!-- 父组件模板 --> <div id="events-example"> <p>Messages: {{ messages | json }}</p> <child></child> </div> // 注册子组件 // 将当前消息派发出去 Vue.component('child', { template: '#child-template', data: function () { return { msg: 'hello' } }, methods: { notify: function () { if (this.msg.trim()) { this.$dispatch('child-msg', this.msg) this.msg = '' } } } }) // 初始化父组件 // 将收到消息时将事件推入一个数组 var parent = new Vue({ el: '#events-example', data: { messages: [] }, // 在创建实例时 `events` 选项简单地调用 `$on` events: { 'child-msg': function (msg) { // 事件回调内的 `this` 自动绑定到注册它的实例上 this.messages.push(msg) } } })
效果:
使用v-on绑定自定义事件
在模板中子组件用到的地方声明事件处理器,为此子组件可以用v-on监听自定义事件:
4084e2349312ebcd04e4de37381def6c7d4dd9c7239aac360e401efe89cbb393
当子组件触发了 "child-msg" 事件,父组件的 handleIt 方法将被调用。所有影响父组件状态的代码放到父组件的 handleIt 方法中;子组件只关注触发事件。
子组件索引
使用v-ref为子组件指定一个索引ID,可以直接访问子组件
<div id="parent"> <user-profile v-ref:profile></user-profile> </div> var parent = new Vue({ el: '#parent' }) // 访问子组件 var child = parent.$refs.profile
使用Slot分发内容
内容分发:混合父组件的内容与子组件自己的模板的方式,使用特殊的58cb293b8600657fad49ec2c8d37b472元素作为原始内容的插槽。
编译作用域
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。
绑定子组件内的指令到一个组件的根节点:
Vue.component('child-component', { // 有效,因为是在正确的作用域内 template: '<div v-show="someChildProperty">Child</div>', data: function () { return { someChildProperty: true } } })
类似地,分发内容是在父组件作用域内编译。
单个slot
父组件的内容将被抛弃,除非子组件模板包含58cb293b8600657fad49ec2c8d37b472,如果子组件模板只有一个没有特性的slot,父组件的整个内容将插到slot所在的地方并替换它。
58cb293b8600657fad49ec2c8d37b472 标签的内容视为回退内容。回退内容在子组件的作用域内编译,当宿主元素为空并且没有内容供插入时显示这个回退内容。
假定 my-component 组件有下面模板:
<div> <h1>This is my component!</h1> <slot>
如果没有分发内容则显示我。
</slot> </div>
父组件模板:
<my-component> <p>This is some original content</p> <p>This is some more original content</p> </my-component>
渲染结果:
<div> <h1>This is my component!</h1> <p>This is some original content</p> <p>This is some more original content</p> </div>
具名slot
58cb293b8600657fad49ec2c8d37b472元素可以用一个特殊特性name配置如何分发内容,多个slot可以有不同的名字,具名slot将匹配内容片段中有对应slot特性的元素。
仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的回退插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。
动态组件
多个组件可以使用同一个挂载点,然后动态地在它们之间切换,使用保留的8c05085041e56efcb85463966dd1cb7e元素,动态地绑定到它的is特性:
new Vue({ el: 'body', data: { currentView: 'home' }, components: { home: { /* ... */ }, posts: { /* ... */ }, archive: { /* ... */ } } }) <component :is="currentView"> <!-- 组件在 vm.currentview 变化时改变 --> </component> keep-alive
把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。
39a981128a40da37853cce84bffb2ba2
b2b0822175891cddec63f9cdd3f18ba9
2724ec0ed5bf474563ac7616c8d7a3cd
activate钩子
控制组件切换时长,activate 钩子只作用于动态组件切换或静态组件初始化渲染的过程中,不作用于使用实例方法手工插入的过程中。
Vue.component('activate-example', { activate: function (done) { var self = this loadDataAsync(function (data) { self.someData = data done() }) } })
transition-mode
transition-mode 特性用于指定两个动态组件之间如何过渡。
在默认情况下,进入与离开平滑地过渡。这个特性可以指定另外两种模式:
in-out:新组件先过渡进入,等它的过渡完成之后当前组件过渡出去。
out-in:当前组件先过渡出去,等它的过渡完成之后新组件过渡进入。
示例:
<!-- 先淡出再淡入 --> <component :is="view" transition="fade" transition-mode="out-in"> </component> .fade-transition { transition: opacity .3s ease; } .fade-enter, .fade-leave { opacity: 0; }
Vue.js 组件 API 来自三部分——prop,事件和 slot:
prop 允许外部环境传递数据给组件;
事件 允许组件触发外部环境的 action;
slot allows the external environment to insert content into the component's view structure.