Vue.js组件使用开发实例教程
组件
组件可以扩展HTML元素,封装可重用的代码,在较高的层面上,组件是自定义元素,vue.js的编译器为它添加特殊功能,在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展。
Vue.js的组件可以理解为预先定义好了行为的ViewModel类。一个组件可以预定义很多选项,但最核心的是以下几个:
模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。
初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。
接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。参数默认是单向绑定(由上至下),但也可以显式地声明为双向绑定。
方法(methods):对数据的改动操作一般都在组件的方法内进行。可以通过v-on指令将用户输入事件和组件方法进行绑定。
生命周期钩子函数(lifecyclehooks):一个组件会触发多个生命周期钩子函数,比如created,attached,destroyed等等。在这些钩子函数中,我们可以封装一些自定义的逻辑。和传统的MVC相比,可以理解为Controller的逻辑被分散到了这些钩子函数中。
私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。由于全局注册资源容易导致命名冲突,一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用。
除此之外,同一颗组件树之内的组件之间还可以通过内建的事件API来进行通信。Vue.js提供了完善的定义、复用和嵌套组件的API,让开发者可以像搭积木一样用组件拼出整个应用的界面。
组件大大提高了代码的效率和维护性以及复用率。
使用组件
注册
1.创建一个组件构造器:
varMyComponent=Vue.extend({ //选项 })
2.将构造器用做组件,用Vue.component(tag,constructor)注册:
Vue.component('my-component',MyComponent)
3.在父实例的模块中以自定义元素<my-component>的形式使用:
<divid="example"> <my-component></my-component> </div>
例子:
<divid="example"> <my-component></my-component> </div> //定义 varMyComponent=Vue.extend({ template:'<div>Acustomcomponent!</div>' }) //注册 Vue.component('my-component',MyComponent) //创建根实例 newVue({ el:'#example' })
渲染为:
<divid="example"> <div>Acustomcomponent!</div> </div>
组件的模板替换了自定义元素,自定义元素的作用只是作为一个挂载点。可以用实例选项replace决定是否替换。
局部注册
用实例选项components注册,不需要全局注册每个组件,可以让组件只能用在其他组件内:
varChild=Vue.extend({/*...*/}) varParent=Vue.extend({ template:'...', components:{ //<my-component>只能用在父组件模板内 'my-component':Child } })
这种封装也适用于其它资源,如指令、过滤器和过渡。
注册语法糖
//在一个步骤中扩展与注册 Vue.component('my-component',{ template:'<div>Acustomcomponent!</div>' }) //局部注册也可以这么做 varParent=Vue.extend({ components:{ 'my-component':{ template:'<div>Acustomcomponent!</div>' } } })
组件选项问题
传入Vue构造器的多数选项也可以用在Vue.extend()中,除了data和el,如果简单的把一个对象作为data选项传给Vue.extend(),则所有的实例将共享同一个data对象,因此我们应当使用一个函数作为data选项,让这个函数返回一个新对象:
varMyComponent=Vue.extend({ data:function(){ return{a:1} } })
模板解析
Vue的模板是DOM模板,使用浏览器原生的解析器,所以它必须是有效的HTML片段,一些HTML元素对什么元素可以放在它里面有限制,常见的限制有:
a不能包含其它的交互元素(如按钮,链接)
ul和ol只能直接包含li
select只能包含option和optgroup
table只能直接包含thead,tbody,tfoot,tr,caption,col,colgroup
tr只能直接包含th和td
在实际中,这些限制会导致意外的结果。尽管在简单的情况下它可能可以工作,但是你不能依赖自定义组件在浏览器验证之前的展开结果。例如
<my-select><option>...</option></my-select>不是有效的模板,即使my-select组件最终展开为<select>...</select>。
另一个结果是,自定义标签(包括自定义元素和特殊标签,如<component>、<template>、<partial>)不能用在ul,select,table等对内部元素有限制的标签内。放在这些元素内部的自定义标签将被提到元素的外面,因而渲染不正确。
对于自定义元素,应当使用is特性:
<table>
<tris="my-component"></tr> </table> //<template>不能用在<table>内,这时应使用<tbody>,<table>可以有多个<tbody> <table> <tbodyv-for="iteminitems"> <tr>Evenrow</tr> <tr>Oddrow</tr> </tbody> </table>
Props
使用props传递数据
组件实例的作用域是孤立的,可以使用props把数组传给子组件,props是组件数据的一个字段,期望从父组件传下来,子组件需要显式地用props选项声明props:
Vue.component('child',{ //声明props props:['msg'], //prop可以用在模板内 //可以用`this.msg`设置 template:'<span>{{msg}}</span>' })
然后向它传入一个普通字符串:
<childmsg="hello!"></child>
动态props
用v-bind绑定动态props到父组件的数据,每当父组件的数据变化时,也会传导给子组件:
<div> <inputv-model="parentMsg"> <childv-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。
<!--子组件模板--> <templateid="child-template"> <inputv-model="msg"> <buttonv-on:click="notify">DispatchEvent</button> </template> <!--父组件模板--> <divid="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='' } } } }) //初始化父组件 //将收到消息时将事件推入一个数组 varparent=newVue({ el:'#events-example', data:{ messages:[] }, //在创建实例时`events`选项简单地调用`$on` events:{ 'child-msg':function(msg){ //事件回调内的`this`自动绑定到注册它的实例上 this.messages.push(msg) } } })
效果:
使用v-on绑定自定义事件
在模板中子组件用到的地方声明事件处理器,为此子组件可以用v-on监听自定义事件:
<childv-on:child-msg="handleIt"></child>
当子组件触发了"child-msg"事件,父组件的handleIt方法将被调用。所有影响父组件状态的代码放到父组件的handleIt方法中;子组件只关注触发事件。
子组件索引
使用v-ref为子组件指定一个索引ID,可以直接访问子组件
<divid="parent"> <user-profilev-ref:profile></user-profile> </div> varparent=newVue({el:'#parent'}) //访问子组件 varchild=parent.$refs.profile
使用Slot分发内容
内容分发:混合父组件的内容与子组件自己的模板的方式,使用特殊的<slot>元素作为原始内容的插槽。
编译作用域
父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。
绑定子组件内的指令到一个组件的根节点:
Vue.component('child-component',{ //有效,因为是在正确的作用域内 template:'<divv-show="someChildProperty">Child</div>', data:function(){ return{ someChildProperty:true } } })
类似地,分发内容是在父组件作用域内编译。
单个slot
父组件的内容将被抛弃,除非子组件模板包含<slot>,如果子组件模板只有一个没有特性的slot,父组件的整个内容将插到slot所在的地方并替换它。
<slot>标签的内容视为回退内容。回退内容在子组件的作用域内编译,当宿主元素为空并且没有内容供插入时显示这个回退内容。
假定my-component组件有下面模板:
<div> <h1>Thisismycomponent!</h1> <slot>
如果没有分发内容则显示我。
</slot> </div>
父组件模板:
<my-component> <p>Thisissomeoriginalcontent</p> <p>Thisissomemoreoriginalcontent</p> </my-component>
渲染结果:
<div> <h1>Thisismycomponent!</h1> <p>Thisissomeoriginalcontent</p> <p>Thisissomemoreoriginalcontent</p> </div>
具名slot
<slot>元素可以用一个特殊特性name配置如何分发内容,多个slot可以有不同的名字,具名slot将匹配内容片段中有对应slot特性的元素。
仍然可以有一个匿名slot,它是默认slot,作为找不到匹配的内容片段的回退插槽。如果没有默认的slot,这些找不到匹配的内容片段将被抛弃。
动态组件
多个组件可以使用同一个挂载点,然后动态地在它们之间切换,使用保留的<component>元素,动态地绑定到它的is特性:
newVue({ el:'body', data:{ currentView:'home' }, components:{ home:{/*...*/}, posts:{/*...*/}, archive:{/*...*/} } }) <component:is="currentView"> <!--组件在vm.currentview变化时改变--> </component>
keep-alive
把切换出去的组件保留在内存中,可以保留它的状态或避免重新渲染。
<component:is="currentView"keep-alive>
<!--非活动组件将被缓存-->
</component>
activate钩子
控制组件切换时长,activate钩子只作用于动态组件切换或静态组件初始化渲染的过程中,不作用于使用实例方法手工插入的过程中。
Vue.component('activate-example',{ activate:function(done){ varself=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.3sease; } .fade-enter,.fade-leave{ opacity:0; }
Vue.js组件API来自三部分——prop,事件和slot:
prop允许外部环境传递数据给组件;
事件允许组件触发外部环境的action;
slot允许外部环境插入内容到组件的视图结构内。
以上所述是小编给大家介绍的Vue.js组件使用开发实例教程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!