Vue.js组件使用开发实例教程


Posted in Javascript onNovember 01, 2016

组件

组件可以扩展HTML元素,封装可重用的代码,在较高的层面上,组件是自定义元素,vue.js的编译器为它添加特殊功能,在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展。

Vue.js的组件可以理解为预先定义好了行为的ViewModel类。一个组件可以预定义很多选项,但最核心的是以下几个:

模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。

初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。

接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。参数默认是单向绑定(由上至下),但也可以显式地声明为双向绑定。

方法(methods):对数据的改动操作一般都在组件的方法内进行。可以通过v-on指令将用户输入事件和组件方法进行绑定。

生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,比如created,attached,destroyed等等。在这些钩子函数中,我们可以封装一些自定义的逻辑。和传统的MVC相比,可以理解为 Controller的逻辑被分散到了这些钩子函数中。

私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。由于全局注册资源容易导致命名冲突,一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用。

除此之外,同一颗组件树之内的组件之间还可以通过内建的事件API来进行通信。Vue.js提供了完善的定义、复用和嵌套组件的API,让开发者可以像搭积木一样用组件拼出整个应用的界面。

组件大大提高了代码的效率和维护性以及复用率。

使用组件

注册

1.创建一个组件构造器:

var MyComponent = Vue.extend({
//选项
})

2.将构造器用做组件,用Vue.component(tag,constructor)注册:

Vue.component('my-component',MyComponent)

3.在父实例的模块中以自定义元素<my-component>的形式使用:

<div id = "example">
<my-component></my-component>
</div>

例子:

<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'
})

渲染为:

<div id = "example">
<div>A custom component!</div>
</div>

组件的模板替换了自定义元素,自定义元素的作用只是作为一个挂载点。可以用实例选项 replace 决定是否替换。

局部注册

用实例选项components注册,不需要全局注册每个组件,可以让组件只能用在其他组件内:

var Child = Vue.extend({ /* ... */ })
var Parent = Vue.extend({
template: '...',
components: {
// <my-component> 只能用在父组件模板内
'my-component': Child
}
})

这种封装也适用于其它资源,如指令、过滤器和过渡。

注册语法糖

// 在一个步骤中扩展与注册
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// 局部注册也可以这么做
var Parent = Vue.extend({
components: {
'my-component': {
template: '<div>A custom component!</div>'
}
}
})

组件选项问题

传入Vue构造器的多数选项也可以用在Vue.extend()中,除了data和el,如果简单的把一个对象作为data选项传给Vue.extend(),则所有的实例将共享同一个data对象,因此我们应当使用一个函数作为data选项,让这个函数返回一个新对象:

var MyComponent = 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>

<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

使用props传递数据

组件实例的作用域是孤立的,可以使用props把数组传给子组件,props是组件数据的一个字段,期望从父组件传下来,子组件需要显式地用props选项声明props:

Vue.component('child', {
// 声明 props
props: ['msg'],
// prop 可以用在模板内
// 可以用 `this.msg` 设置
template: '<span>{{ msg }}</span>'
})

然后向它传入一个普通字符串:

<child msg="hello!"></child>

动态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监听自定义事件:

<child v-on:child-msg="handleIt"></child>

当子组件触发了 "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分发内容

内容分发:混合父组件的内容与子组件自己的模板的方式,使用特殊的<slot>元素作为原始内容的插槽。

编译作用域

父组件模板的内容在父组件作用域内编译;子组件模板的内容在子组件作用域内编译。

绑定子组件内的指令到一个组件的根节点:

Vue.component('child-component', {
// 有效,因为是在正确的作用域内
template: '<div v-show="someChildProperty">Child</div>',
data: function () {
return {
someChildProperty: true
}
}
})

类似地,分发内容是在父组件作用域内编译。

单个slot

父组件的内容将被抛弃,除非子组件模板包含<slot>,如果子组件模板只有一个没有特性的slot,父组件的整个内容将插到slot所在的地方并替换它。

<slot> 标签的内容视为回退内容。回退内容在子组件的作用域内编译,当宿主元素为空并且没有内容供插入时显示这个回退内容。

假定 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

<slot>元素可以用一个特殊特性name配置如何分发内容,多个slot可以有不同的名字,具名slot将匹配内容片段中有对应slot特性的元素。

仍然可以有一个匿名 slot,它是默认 slot,作为找不到匹配的内容片段的回退插槽。如果没有默认的 slot,这些找不到匹配的内容片段将被抛弃。

动态组件

多个组件可以使用同一个挂载点,然后动态地在它们之间切换,使用保留的<component>元素,动态地绑定到它的is特性:

new Vue({
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) {
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 允许外部环境插入内容到组件的视图结构内。

以上所述是小编给大家介绍的Vue.js组件使用开发实例教程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
javascript Firefox与IE 替换节点的方法
Feb 24 Javascript
javascript算法学习(直接插入排序)
Apr 12 Javascript
JQury slideToggle闪烁问题及解决办法
Jul 05 Javascript
修复jQuery tablesorter无法正确排序的bug(加千分位数字后)
Mar 30 Javascript
整理JavaScript对DOM中各种类型的元素的常用操作
May 05 Javascript
jq实现左滑显示删除按钮,点击删除实现删除数据功能(推荐)
Aug 23 Javascript
JS实现换肤功能的方法实例详解
Jan 30 Javascript
vue增加强缓存和版本号的实现方法
May 01 Javascript
详解es6新增数组方法简便了哪些操作
May 09 Javascript
使vue实现jQuery调用的两种方法
May 12 jQuery
在layui.use 中自定义 function 的正确方法
Sep 16 Javascript
让你30分钟快速掌握vue3教程
Oct 26 Javascript
js调用父框架函数与弹窗调用父页面函数的简单方法
Nov 01 #Javascript
js判断出两个字符串最大子串的函数实现方法
Nov 01 #Javascript
JavaScript中全选、全不选、反选、无刷新删除、批量删除、即点即改入库(在yii框架中操作)的代码分享
Nov 01 #Javascript
JS中跨页面调用变量和函数的方法(例如a.js 和 b.js中互相调用)
Nov 01 #Javascript
js print打印网页指定区域内容的简单实例
Nov 01 #Javascript
js文件中直接alert()中文出来的是乱码的解决方法
Nov 01 #Javascript
浅谈JavaScript事件绑定的常用方法及其优缺点分析
Nov 01 #Javascript
You might like
thinkphp框架下404页面设置 仅三步
2016/05/14 PHP
PHP编程之设置apache虚拟目录
2016/07/08 PHP
JavaScript中null与undefined分析
2009/07/25 Javascript
javaScript array(数组)使用字符串作为数组下标的方法
2013/11/19 Javascript
javascript实现在某个元素上阻止鼠标右键事件的方法和实例
2014/08/12 Javascript
控制台报错object is not a function的解决方法
2014/08/24 Javascript
JavaScript内存管理介绍
2015/03/13 Javascript
jQuery实现的多屏图像图层切换效果实例
2015/05/07 Javascript
JavaScript中实现无缝滚动、分享到侧边栏实例代码
2016/04/06 Javascript
vue2滚动条加载更多数据实现代码
2017/01/10 Javascript
JavaScript日期选择功能示例
2017/01/16 Javascript
前端页面文件拖拽上传模块js代码示例
2017/05/19 Javascript
浅谈struts1 &amp; jquery form 文件异步上传
2017/05/25 jQuery
纯 JS 实现放大缩小拖拽功能(完整代码)
2019/11/25 Javascript
解决echarts vue数据更新,视图不更新问题(echarts嵌在vue弹框中)
2020/07/20 Javascript
Python fileinput模块使用实例
2015/05/28 Python
Python 操作文件的基本方法总结
2017/08/10 Python
python 将list转成字符串,中间用符号分隔的方法
2018/10/23 Python
python之当你发现QTimer不能用时的解决方法
2019/06/21 Python
python数据化运营的重要意义
2019/11/25 Python
windows下Pycharm安装opencv的多种方法
2020/03/05 Python
python实现将range()函数生成的数字存储在一个列表中
2020/04/02 Python
python matplotlib:plt.scatter() 大小和颜色参数详解
2020/04/14 Python
TensorFlow的reshape操作 tf.reshape的实现
2020/04/19 Python
纯CSS3实现滚动的齿轮动画效果
2014/06/05 HTML / CSS
美国开幕式潮店:Opening Ceremony
2018/02/10 全球购物
Otticanet美国:最顶尖的世界名牌眼镜, 能得到打折季的价格
2019/03/10 全球购物
企业管理部经理岗位职责
2013/12/24 职场文书
模具设计与制造专业推荐信
2014/02/16 职场文书
英语一分钟演讲稿
2014/04/29 职场文书
企业党建工作总结2015
2015/05/26 职场文书
2015年加油站站长工作总结
2015/05/27 职场文书
个人工作总结怎么写?
2019/04/09 职场文书
分享一些Java的常用工具
2021/06/11 Java/Android
详解OpenCV曝光融合
2022/04/29 Python
SQL Server使用CROSS APPLY与OUTER APPLY实现连接查询
2022/05/25 SQL Server