强大Vue.js组件浅析


Posted in Javascript onSeptember 12, 2016

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

如何注册组件?

需要使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。Vue.extend方法格式如下: 

var MyComponent = Vue.extend({
 // 选项...后面再介绍
})

如果想要其他地方使用这个创建的组件,还得个组件命个名: 

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

命名之后即可在HTML标签中使用这个组件名称,像使用DOM元素一样。下面来看看一个完整的组件注册和使用例子。

html代码: 

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

js代码: 

// 定义
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

嵌套组件
组件本身也可以包含组件,下面的parent组件就包含了一个命名为child-component组件,但这个组件只能被parent组件使用: 

var child = Vue.extend({
 template: '<div>A custom component!</div>'
});
var parent = Vue.extend({

 template: '<div>Parent Component: <child-component></child-component></div>',
 components: {
 'child-component': child
 }
});
Vue.component("parent-component", parent);

上面的定义过程比较繁琐,也可以不用每次都调用Vue.component和Vue.extend方法: 

// 在一个步骤中扩展与注册
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})

// 局部注册也可以这么做
var Parent = Vue.extend({
 components: {
 'my-component': {
  template: '<div>A custom component!</div>'
 }
 }
})

动态组件

多个组件可以使用同一个挂载点,然后动态的在他们之间切换。使用保留的<component>元素,动态地绑定到它的is特性。下面的列子在同一个vue实例下挂了home、posts、archive三个组件,通过特性currentView动态切换组件显示。

html代码: 

<div id="dynamic">
 <button id="home">Home</button>
 <button id="posts">Posts</button>
 <button id="archive">Archive</button>
 <br>
 <component :is="currentView"></component>
</div>

js代码: 

var vue = new Vue({
 el:"#dynamic",
 data: {
 currentView: "home"
 },
 components: {
 home:{
  template: "Home"
 },
 posts: {
  template: "Posts"
 },
 archive: {
  template: "Archive"
 }
 }
});
document.getElementById("home").onclick = function(){
vue.currentView = "home";
};
document.getElementById("posts").onclick = function(){
vue.currentView = "posts";
};
document.getElementById("archive").onclick = function(){
vue.currentView = "archive";
};

组件和v-for 
<my-component v-for="item in items"></my-component> 

不能传递数据给组件,因为组件的作用域是独立的。为了传递数据给组件,应当使用props: 

<my-component
v-for="item in items"
:item="item"
:index="$index">
</my-component>

不自动把 item 注入组件的原因是这会导致组件跟当前 v-for 紧密耦合。显式声明数据来自哪里可以让组件复用在其它地方。

 深入响应式原理

在组件绑定数据时,如何绑定才能够有效,并且可动态修改、添加属性?看看下面的原理介绍。

如何追踪变化:把一个不同对象传给vue实例作为data的选项,vue.js将遍历它的属性,用Object.defineProperty将它转换为getter/setter。这是ES5特性,所有vue.js不支持IE8或更低版本。

模板中每个指令/数据绑定都有一个对应的watcher对象,在计算过程中它把属性记录为依赖。之后当依赖的setter被调用时 ,会触发watcher重新计算。流程如下所示: 

强大Vue.js组件浅析

变化检测问题:vue.js不能检测到对象属性的添加或删除,属性必须在data上才能让vue.js转换它为getter/setter模式,才能有响应。例如: 

var data = { a: 1 };
var vm = new Vue({
data: data
});
// `vm.a` 和 `data.a` 现在是响应的
vm.b = 2
// `vm.b` 不是响应的
data.b = 2
// `data.b` 不是响应的

不过,也有办法在实例创建后添加属性并且让它是相应的。可以使用set(key,value)实例方法: 

vm. set('b', 2)
// `vm.b` 和 `data.b` 现在是响应的 

对于普通对象可以使用全局方法:Vue.set(object, key, value):
Vue.set(data, 'c', 3)
// `vm.c` 和 `data.c` 现在是响应的 

初始化数据:尽管Vue.js提供动态的添加相应属性,还是推荐在data对象上声明所有的相应属性。

不这么做: 

var vm = new Vue({
 template: '<div>{{msg}}</div>'
})
// 然后添加 `msg`
vm.$set('msg', 'Hello!')

应该这么做: 

var vm = new Vue({
 data: {
 // 以一个空值声明 `msg`
 msg: ''
 },
 template: '<div>{{msg}}</div>'
})
// 然后设置 `msg`
vm.msg = 'Hello!'
 

组件完整案例
下面介绍的例子实现了模态窗口功能,代码也比较简单。

html代码:

<!-- 实现script定义一个模板 -->
<script type="x/template" id="modal-template">
 <!--模板是否显示通过v-show="show"来设置, transition设置动画效果-->
 <div class="modal-mask" v-show="show" transition="modal">
 <div class="modal-wrapper">
  <div class="modal-container">
  <div class="modal-header">
   <!--slot 相当于header占位符-->
   <slot name="header">
   default header
   </slot>
  </div>
  <div class="modal-body">
   <!--slot 相当于body占位符-->
   <slot name="body">
   default body
   </slot>
  </div>
  <div class="modal-footer">
   <!--slot 相当于footer占位符-->
   <slot name="footer">
   default footer
   </slot>
   <button class="modal-default-button" @click="show = false">OK</button>
  </div>
  </div>
 </div>
 </div>
</script>
<div id="app">
 <!--点击按钮时设置vue实例特性showModal的值为true-->
 <button id="show-modal" @click="showModal = true">show modal</button>
 <!--modal是自定义的一个插件,插件的特性show绑定vue实例的showModal特性-->
 <modal :show.sync="showModal">
 <!--替换modal插件中slot那么为header的内容-->
 <h3 slot="header">Custom Header</h3>
 </modal>
</div>

 js代码: 

//定义一个插件,名称为modal
Vue.component("modal", {
 //插件的模板绑定id为modal-template的DOM元素内容
 template: "#modal-template",
 props: {
 //特性,类型为布尔
 show:{
  type: Boolean,
  required: true,
  twoWay: true
 }
 }
});
//实例化vue,作用域在id为app元素下,
new Vue({
 el: "#app",
 data: {
 //特性,默认值为false
 showModal: false
 }
});

css代码: 

.modal-mask {
 position: fixed;
 z-index: 9998;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
 background-color: rgba(0, 0, 0, .5);
 display: table;
 transition: opacity .3s ease;
}

.modal-wrapper {
 display: table-cell;
 vertical-align: middle;
}

.modal-container {
 width: 300px;
 margin: 0px auto;
 padding: 20px 30px;
 background-color: #fff;
 border-radius: 2px;
 box-shadow: 0 2px 8px rgba(0, 0, 0, .33);
 transition: all .3s ease;
 font-family: Helvetica, Arial, sans-serif;
}

.modal-header h3 {
 margin-top: 0;
 color: #42b983;
}

.modal-body {
 margin: 20px 0;
}

.modal-default-button {
 float: right;
}

/*
* the following styles are auto-applied to elements with
* v-transition="modal" when their visiblity is toggled
* by Vue.js.
*
* You can easily play with the modal transition by editing
* these styles.
*/

.modal-enter, .modal-leave {
 opacity: 0;
}

.modal-enter .modal-container,
.modal-leave .modal-container {
 -webkit-transform: scale(1.1);
 transform: scale(1.1);
}

本文已被整理到了《Vue.js前端组件学习教程》,欢迎大家学习阅读。

关于vue.js组件的教程,请大家点击专题vue.js组件学习教程进行学习。

由于自己在项目中还没怎么深入使用组件的功能,所以自己对组件的理解也不深入,介绍的比较肤浅,谢谢大家的阅读。

Javascript 相关文章推荐
js页面跳转的问题(跳转到父页面、最外层页面、本页面)
Aug 14 Javascript
jquery实现效果比较好的table选中行颜色
Mar 25 Javascript
修改或扩展jQuery原生方法的代码实例
Jan 13 Javascript
jQuery模拟新浪微博首页滚动效果的方法
Mar 11 Javascript
jQuery插件datepicker 日期连续选择
Jun 12 Javascript
JavaScript实现Base64编码转换
Apr 23 Javascript
EasyUI学习之Combobox级联下拉列表(2)
Dec 29 Javascript
微信小程序 websocket 实现SpringMVC+Spring+Mybatis
Aug 04 Javascript
JavaScript定义函数的三种实现方法
Sep 23 Javascript
Node.js 中使用 async 函数的方法
Nov 20 Javascript
vue中实现左右联动的效果
Jun 22 Javascript
使用layui日期控件laydate对开始和结束时间进行联动控制的方法
Sep 06 Javascript
超详细的JS弹出窗口代码大全
Apr 18 #Javascript
使用JS实现图片展示瀑布流效果的实例代码
Sep 12 #Javascript
关于javascript的一些知识以及循环详解
Sep 12 #Javascript
基于AngularJS实现iOS8自带的计算器
Sep 12 #Javascript
Javascript6中字符串的四个新用法分享
Sep 11 #Javascript
JavaScript制作简单分页插件
Sep 11 #Javascript
关于vue.js弹窗组件的知识点总结
Sep 11 #Javascript
You might like
Bo-Blog专用的给Windows服务器的IIS Rewrite程序
2007/08/26 PHP
[原创]ThinkPHP让../Public在模板不解析(直接输出)的方法
2015/10/09 PHP
Jquery中增加参数与Json转换代码
2009/11/20 Javascript
javascript中的array数组使用技巧
2010/01/31 Javascript
理解Javascript_06_理解对象的创建过程
2010/10/15 Javascript
基于jquery实现的表格分页实现代码
2011/06/21 Javascript
JS实现可展开折叠层的鼠标拖曳效果
2015/10/09 Javascript
AngularJS基础 ng-keypress 指令简单示例
2016/08/02 Javascript
Vue数据驱动模拟实现2
2017/01/11 Javascript
boostrapTable的refresh和refreshOptions区别浅析
2017/01/22 Javascript
详解Vue-基本标签和自定义控件
2017/03/24 Javascript
JavaScript中 DOM操作方法小结
2017/04/25 Javascript
用node-webkit把web应用打包成桌面应用(windows环境)
2018/02/01 Javascript
Angularjs实现控制器之间通信方式实例总结
2018/03/27 Javascript
angularjs $http调用接口的方式详解
2018/08/13 Javascript
浅谈微信小程序之官方UI框架we-ui使用教程
2018/08/20 Javascript
Vue 实现拖动滑块验证功能(只有css+js没有后台验证步骤)
2018/08/24 Javascript
一个Java程序猿眼中的前后端分离以及Vue.js入门(推荐)
2019/04/19 Javascript
vue-router的hooks用法详解
2020/06/08 Javascript
[50:28]LGD女子学院第三期 DOTA2复仇之魂教学
2013/12/24 DOTA
Python IDE PyCharm的基本快捷键和配置简介
2015/11/04 Python
python 线程的暂停, 恢复, 退出详解及实例
2016/12/06 Python
深入分析python中整型不会溢出问题
2018/06/18 Python
Python3多线程基础知识点
2019/02/19 Python
Python collections模块使用方法详解
2019/08/28 Python
Python如何设置指定窗口为前台活动窗口
2020/08/12 Python
StubHub希腊:购买体育赛事、音乐会和剧院门票
2019/08/03 全球购物
Molton Brown美国官网:奢华美容、香水、沐浴和身体护理
2020/09/02 全球购物
刘胡兰的英雄事迹材料
2014/02/11 职场文书
维修工先进事迹
2014/05/29 职场文书
旅游文化节策划方案
2014/06/06 职场文书
2014年干部培训工作总结
2014/12/17 职场文书
销售业务员岗位职责
2015/02/13 职场文书
晚会开幕词范文
2016/03/04 职场文书
在pyCharm中下载第三方库的方法
2021/04/18 Python
Pytorch使用shuffle打乱数据的操作
2021/05/20 Python