Vue.js 前端开发 快速入门与专业应用

978-7-115-44493-6
作者: 陈陆扬
译者:
编辑: 赵轩

图书目录:

详情

本书分为10章:简介,基础特性,指令,过滤器,过渡,组件,状态管理,常用插件,工程实例,Weex打包。从简单的单个实例和基础语法,到工程实例,将系统的讲述Vue.js在项目中的适用场景和具体操作。 书的特点在于案例详实,使读者体会到框架的优点和便捷之处,提升开发效率,最后能将Vue.js运用到实际项目中,避免纸上谈兵的尴尬。

图书摘要

版权信息

书名:Vue.js 前端开发 快速入门与专业应用

ISBN:978-7-115-44493-6

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

• 著    陈陆扬

  责任编辑 赵 轩

• 人民邮电出版社出版发行  北京市丰台区成寿寺路11号

  邮编 100164  电子邮件 315@ptpress.com.cn

  网址 http://www.ptpress.com.cn

• 读者服务热线:(010)81055410

  反盗版热线:(010)81055315


本书主要介绍Vue.js的使用方法和在实际项目中的运用,它既可以在一个页面中单独使用,也可以将整站都构建成单页面应用。为了便于理解,本书会从传统的开发角度切入,先从数据渲染、事件绑定等方面介绍在Vue.js中的使用方法,然后渐进到Vue.js自身的特性,例如数据绑定、过滤器、指令以及最重要的组件部分。除了框架用法外,本书还介绍了和Vue.js相关的重要插件和构建工具,这些工具有助于帮助用户构建一个完整的单页面应用,而不仅仅是停留在个人DEMO阶段的试验品。而对于复杂项目,Vue.js也提供了对应的状态管理工具Vuex,降低项目的开发和维护成本。鉴于完稿前,Vue.js 2.0已正式发布完毕,本书也在相关用法上对比了1.0和2.0的区别,并补充了render函数和服务端渲染等特性。

本书适用于尚未接触过MVVM类前端框架的开发者,或者初步接触Vue.js的开发者,以及实际应用Vue.js开发项目的开发者。


近年来,前端框架的发展依旧火热,新的框架和名词依旧不停地出现在开发者眼前,而且开发模式也产生了一定的变化。目前来看,前端MVVM框架的出现给开发者带来了不小的便利,其中的代表就有Angular.js、React.js以及本书中将要介绍的Vue.js。这些框架的产生使得开发者能从过去手动维护DOM状态的繁琐操作中解脱出来,尽可能地让DOM的更新操作是自动的,状态变化的时候就自动更新到正确的状态。不过,新框架的引入不可避免的就是学习成本的增加以及框架普及性的问题,相对于Angular.js和React.js而言,Vue.js的学习曲线则比较平稳。目前在GitHub上已经获得了超过30000的star,成为了时下无论从实用性还是普遍性来说都是可靠的MVVM框架选择之一。

首次听说Vue.js的时候,都是介绍说体积小、适合移动端、使用简单,等等。但一开始对于新框架我一直持观望态度,毕竟前端框架更新太快,而且这又是个个人项目,仅由作者尤雨溪一人维护,不像Angular.js和React.js那样有公司支持。后来为了解决一个移动端的项目,我才正式接触了Vue.js。由于项目本身天然存在组件这个概念,并且需要在手机上运行,调研后觉得应该没有比Vue.js更适合的工具了。在使用过程中,逐渐体会到了Vue.js的便利,数据绑定及组件系统对于提高开发效率和代码复用性来说都有相当大的帮助,并且初期对线上项目使用这种新框架的顾虑也渐渐消除了,即使随着后期复杂度的增加也并没有对项目的开发和维护成本造成影响。

本书主要从我自身的学习和开发经验出发,介绍了Vue.js的基础用法和特性,包括Vue.js的一些插件用法,用于解决客户端路由和大规模状态管理,以及打包发布等构建工具,便于正式用于线上环境。

最后,感谢Vue.js作者尤雨溪先生为前端开发者提供了这款优秀的框架,使得开发者能够更好地应对项目复杂度;也感谢人民邮电出版社的大力支持,写书的过程的确对人是一种折磨和考验;最后感谢每天早上4点多就开始叫我起床的两只猫,它们对本书的进度的确起到了很好的推动作用。


近几年,互联网前端行业发展得依旧迅猛,涌现出了很多优秀的框架,同时这些框架也正在逐渐改变我们传统的前端开发方式。Google的AngularJS、Facebook的ReactJS,这些前端MVC(MVVM)框架的出现和组件化开发的普及和规范化,既改变了原有的开发思维和方式,也使得前端开发者加快脚步,更新自己的知识结构。2014年2月,原Google员工尤雨溪公开发布了自己的前端库——Vue.js,时至今日,Vue.js在GitHub上已经收获超过30000star,而且也有越来越多的开发者在实际的生产环境中运用它。

本书主要以Vue.js 1.0.26版本为基准进行说明,Vue.js 2.0版本与之不同的地方,会在对应章节中说明。

单独来讲,Vue.js被定义成一个用来开发Web界面的前端库,是个非常轻量级的工具。Vue.js本身具有响应式编程和组件化的特点。

所谓响应式编程,即为保持状态和视图的同步,这个在大多数前端MV*(MVC/MVVM/MVW)框架,不管是早期的backbone.js还是现在AngularJS都对这一特性进行了实现(也称之为数据绑定),但这几者的实现方式和使用方式都不相同。相比而言,Vue.js使用起来更为简单,也无需引入太多的新概念,声明实例new Vue({ data : data })后自然对data里面的数据进行了视图上的绑定。修改data的数据,视图中对应数据也会随之更改。

Vue.js的组件化理念和ReactJS异曲同工——“一切都是组件”,可以将任意封装好的代码注册成标签,例如:Vue.component('example', Example),可以在模板中以<example></example>的形式调用。如果组件抽象得合理,这在很大程度上能减少重复开发,而且配合Vue.js的周边工具vue-loader,我们可以将一个组件的CSS、HTML和js都写在一个文件里,做到模块化的开发。

除此之外,Vue.js也可以和一些周边工具配合起来,例如vue-router和vue-resource,支持了路由和异步请求,这样就满足了开发单页面应用的基本条件。

相比较Angularjs和ReactJS,Vue.js一直以轻量级,易上手被称道。MVVM的开发模式也使前端从原先的DOM操作中解放出来,我们不再需要在维护视图和数据的统一上花大量的时间,只需要关注于data的变化,代码变得更加容易维护。虽然社区和插件并没有一些老牌的开源项目那么丰富,但满足日常的开发是没有问题的。Vue.js 2.0也已经发布了beta版本,渲染层基于一个轻量级的 virtual-DOM 实现,在大多数场景下初始化渲染速度和内存消耗都提升了 2~4 倍。而阿里也开源了weex(可以理解成ReactJS-Native和ReacJS的关系),这也意味着Vue.js在移动端有了更多的可能性。

不过,对于为什么要选择使用一个框架,都需要建立在一定的项目基础上。如果脱离实际项目情况我们来谈某个框架的优劣,以及是否采用这种框架,我觉得是不够严谨的。

作为新兴的前端框架,Vue.js也抛弃了对IE8的支持,在移动端支持到Android 4.2+和iOS 7+。所以如果你在一家比较传统,还需要支持IE6的公司的话,你或许就可以考虑其他的解决方案了(或者说服你的老板)。另外,在传统的前后端混合(通过后端模板引擎渲染)的项目中,Vue.js也会受到一定的限制,Vue实例只能和后端模板文件混合在一起,获取的数据也需要依赖于后端的渲染,这在处理一些JSON对象和数组的时候会有些麻烦。

理想状态下,我们能直接在前后端分离的新项目中使用Vue.js最合适。这能最大程度上发挥Vue.js的优势和特性,熟悉后能极大的提升我们的开发效率以及代码的复用率。尤其是移动浏览器上,Vue.js压缩后只有18KB,而且没有其他的依赖。

现在来看一下我们第一个Vue.js项目,按照传统,我们来写一个Hello World。

首先,引入Vue.js的方式有很多,你可以采用直接使用CDN,例如:

<script src='http://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js'></script>

也可以通过NPM进行安装:

npm install vue // 最新稳定版本

正确引入Vue.js之后,我们在HTML文件中的内容为:

<div id="app">
 <h1>{{message}}</h1>
</div>

应用的js如下:

var vm = new Vue({
 el : '#app',
 data: {
  message : 'Hello world, I am Vue.js'
 }
});

输出结果为:

这种形式类似于前端模板引擎,我们把js中message值替换了HTML模板中{{message}}这部分。

不过,如果仅仅是这样的例子,我相信你也不会有什么兴趣去使用Vue.js。根据上文对Vue.js的说明,我们继续写两个有关于它特性的例子。

第一个特性是数据绑定,我们可以在运行上述例子的浏览器控制台(console)环境中输入vm.message = 'Hello Vue.js',输出结果就变为了Hello Vue.js。也就说明vm.message和视图中的{{message}}是绑定的,我们无需手动去获取<h1>标签来修改里面的innerHTML。

同样,我们也可以绑定用户输入的数据,视图会随着用户的输入而变化,例如:

<div id="app">
 <h1>Your input is {{ message }}</h1>
 <input type=”text” v-model=”message”>
</div>

vm.message的值会随着用户在input中输入的值的变化而变化,而无需我们手动去获取DOM元素的值再同步到js中。

第二个特性是组件化,简单来说我们可以自己定义HTML标签,并在模板中使用它,例如:

<div id="app">
 <message content='Hello World'></message>
</div> 
<script type="text/javascript">
 var Message = Vue.extend({
  props : ['content'],
  template : '<h1>{{content}}</h1>'
 })
 Vue.component('message', Message);
 var vm = new Vue({
  el : '#app',
 });
</script>

我们在浏览器里最终看到的HTML结果为:

可以看到自定义的标签<message>被替换成了<h1>Hello World</h1>,当然,实际中的组件化远比示例复杂,我们会给组件添加参数及方法,使之能更好地被复用。

如果说这几个例子引起了你对Vue.js的兴趣的话,那接下来我们就会详细地说明它的基础用法和应用场景,以及最终我们如何将它真实地运用到生产环境中。


其实,无论前端框架如何变化,它需要处理的事情依旧是模板渲染、事件绑定、处理用户交互(输入信息或鼠标操作),只不过提供了不同的写法和理念。Vue.js则会通过声明一个实例new Vue({…})标记当前页面的HTML结构、数据的展示及相关事件的绑定。本章主要介绍Vue.js的构造函数的选项对象及用法,以及如何通过Vue.js来实现上述的常规前端功能。

从以前的例子可以看出,Vue.js的使用都是通过构造函数Vue({option})创建一个Vue的实例:var vm = new Vue({})。一个Vue实例相当于一个MVVM模式中的ViewModel,如图2-1所示。

图2-1

在实例化的时候,我们可以传入一个选项对象,包含数据、模板、挂载元素、方法、生命周期钩子等选项。下面就对一些常用的选项对象属性进行具体的说明。

选项中主要影响模板或DOM的选项有el和template,属性replace和template需要一起使用。

el:类型为字符串,DOM元素或函数。其作用是为实例提供挂载元素。一般来说我们会使用css选择符,或者原生的DOM元素。例如el:'#app'。在初始项中指定了el,实例将立即进入编译过程。

template:类型为字符串。默认会将template值替换挂载元素(即el值对应的元素),并合并挂载元素和模板根节点的属性(如果属性具有唯一性,类似id,则以模板根节点为准)。如果replace为false,模板template的值将插入挂载元素内。通过template插入模板的时候,挂载元素的内容都将被互联,除非使用slot进行分发(有关slot内容将在第6章组件中介绍)。在使用template时,我们往往不会把所有的HTML字符串直接写在js里面,这样影响可读性而且也不利于维护。所以经常用'#tpl'的方式赋值,并且在body内容添加<script id="tpl" type="x-template">为标签包含的HTML内容,这样就能将HTML从js中分离开来,示例如下:

<div id="app">
 <p>123</p>
</div>
<script id="tpl" type="x-template">
 <div class='tpl'>
  <p>This is a tpl from script tag</p>
 </div>
</script>
<script type="text/javascript">
 var vm = new Vue({
  el : '#app',
  template : '#tpl'
 });
</script>

最终输出HTML结构为:

Vue.js 2.0 中废除了replace这个参数,并且强制要求每一个Vue.js实例需要有一个根元素,即不允许组件模板为:

<script id="tpl" type="x-template">
 <div class='tpl'>
    …
 </div>
 <div class='tpl'>
    …
 </div>
</script>

这样的兄弟节点为根节点的模板形式,需要改写成:

<script id="tpl" type="x-template">
 <div class='wrapper'>
  <div class='tpl'>
      …
  </div>
  <div class='tpl'>
     …
  </div>
 </div>
</script>

Vue.js实例中可以通过data属性定义数据,这些数据可以在实例对应的模板中进行绑定并使用。需要注意的是,如果传入data的是一个对象,Vue实例会代理起data对象里的所有属性,而不会对传入的对象进行深拷贝。另外,我们也可以引用Vue实例vm中的$data来获取声明的数据,例如:

var data = { a: 1 }
var vm = new Vue({
 data: data
})
vm.$data === data // -> true
vm.a === data.a // -> true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // -> 2
// 反之亦然
data.a = 3
vm.a // -> 3

然后在模板中使用{{a}}就会输出vm.a的值,并且修改vm.a的值,模板中的值会随之改变,我们也会称这个数据为响应式(responsive)数据(具体的用法和特性会在第2.2节的数据绑定中说明)。

需要注意的是,只有初始化时传入的对象才是响应式的,即在声明完实例后,再加上一句vm.$data.b = '2',并在模板中使用{{b}},这时是不会输出字符串'2'的。例如:

<div id="app">
 <p>{{a}}</p>
 <p>{{b}}</p>
</div>
var vm = new Vue({
  el : '#app',
  data : {
   a : 1
  }
});
vm.$data.b = 2;

如果需要在实例化之后加入响应式变量,需要调用实例方法$set, 例如:

vm.$set('b', 2);

不过Vue.js并不推荐这么做,这样会抛出一个异常:

所以,我们应尽量在初始化的时候,把所有的变量都设定好,如果没有值,也可以用undefined或null占位。

另外,组件类型的实例可以通过props获取数据,同data一样,也需要在初始化时预设好。示例:

<my-component title='myTitle' content='myContent'></my-component>
var myComponent = Vue.component('my-component', {
  props : ['title', 'content'],
  template : '<h1>{{title}}</h1><p>{{content}}</p>'
})

我们也可以在上述组件类型实例中同时使用data,但有两个地方需要注意:① data的值必须是一个函数,并且返回值不是原始对象。如果传给组件的data是一个原始对象的话,则在建立多个组件实例时它们就会共用这个data对象,修改其中一个组件实例的数据就会影响到其他组件实例的数据,这显然不是我们所期望的。② data中的属性和props中的不能重名。这两者均会抛出异常:

所以正确的使用方法如下:

var MyComponent = Vue.component('my-component', {
  props : ['title', 'content'],
  data : function() {
   return {
    desc : '123'
   }
  },
  template : '<div> \
    <h1>{{title}}</h1> \
    <p>{{content}}</p> \
    <p>{{desc}}</p> \
   </div>'
})

我们可以通过选项属性methods对象来定义方法,并且使用v-on指令来监听DOM事件,例如:

<button v-on:click="alert"/>alert</button>
new Vue({
 el : '#app',
 data : { a : 1},
 methods : {
  alert : function() {
    alert(this.a);
   }
  }
});

另外,Vue.js实例也支持自定义事件,可以在初始化时传入events对象,通过实例的$emit方法进行触发。这套通信机制常用在组件间相互通信的情况中,例如子组件冒泡触发父组件事件方法,或者父组件广播某个事件,子组件对其进行监听等。这里先简单说明下用法,详细的情况将会在第6章组件中进行说明。

var vm = new Vue({
 el : '#app',
 data : data,
 events : {
  'event.alert' : function() {
   alert('this is event alert :' + this.a);
   }
  }
});
vm.$emit('event.alert');

而Vue.js 2.0 中废弃了events选项属性,不再支持事件广播这类特性,推荐直接使用Vue实例的全局方法$on()/$emit(),或者使用插件Vuex来处理。

Vue.js实例在创建时有一系列的初始化步骤,例如建立数据观察,编译模板,创建数据绑定等。在此过程中,我们可以通过一些定义好的生命周期钩子函数来运行业务逻辑。例如:

var vm = new Vue({
 data: {
  a: 1
 },
 created: function () {
  console.log('created')
 }
})

运行上述例子时,浏览器console中就会打印出created。

下图是实例的生命周期,可以根据提供的生命周期钩子说明Vue.js实例各个阶段的情况,Vue.js 2.0对不少钩子进行了修改,以下一并说明。

Vue.js 实例生命周期(原图出自于Vue.js官网),如图2-2所示。

图2-2

init: 在实例开始初始化时同步调用。此时数据观测、事件等都尚未初始化。2.0中更名为beforeCreate。

created:在实例创建之后调用。此时已完成数据绑定、事件方法,但尚未开始DOM编译,即未挂载到document中。

beforeCompile: 在DOM编译前调用。2.0废弃了该方法,推荐使用created。

beforeMount: 2.0新增的生命周期钩子,在mounted之前运行。

compiled: 在编译结束时调用。此时所有指令已生效,数据变化已能触发DOM更新,但不保证$el已插入文档。2.0中更名为mounted。

ready:在编译结束和$el第一次插入文档之后调用。2.0废弃了该方法,推荐使用mounted。这个变化其实已经改变了ready这个生命周期状态,相当于取消了在$el首次插入文档后的钩子函数。

attached:在vm.$el插入DOM时调用,ready会在第一次attached后调用。操作$el必须使用指令或实例方法(例如$appendTo()),直接操作vm.$el不会触发这个钩子。2.0废弃了该方法,推荐在其他钩子中自定义方法检查是否已挂载。

detached: 同attached类似,该钩子在vm.$el从DOM删除时调用,而且必须是指令或实例方法。2.0中同样废弃了该方法。

beforeDestroy: 在开始销毁实例时调用,此刻实例仍然有效。

destroyed: 在实例被销毁之后调用。此时所有绑定和实例指令都已经解绑,子实例也被销毁。

beforeUpdate: 2.0新增的生命周期钩子,在实例挂载之后,再次更新实例(例如更新data)时会调用该方法,此时尚未更新DOM结构。

updated:2.0新增的生命周期钩子,在实例挂载之后,再次更新实例并更新完DOM结构后调用。

activated:2.0新增的生命周期钩子,需要配合动态组件keep-live属性使用。在动态组件初始化渲染的过程中调用该方法。

deactivated:2.0新增的生命周期钩子,需要配合动态组件keep-live属性使用。在动态组件移出的过程中调用该方法。

可以通过写一个简单的demo来更清楚地了解内部的运行机制,代码如下:

var vm = new Vue({
 el : '#app',
 init: function() {
  console.log('init');
 },
 created: function() {
  console.log('created');
 },
 beforeCompile: function() {
  console.log('beforeCompile');
 },
 compiled: function() {
  console.log('compiled');
 },
 attached: function() {
  console.log('attached');
 },
 dettached: function() {
  console.log('dettached');
 },
 beforeDestroy: function() {
  console.log('beforeDestroy');
 },
 destroyed: function() {
  console.log('destroyed');
 },
 ready: function() {
  console.log('ready');
  // 组件完成后调用$destory()函数,进行销毁
  this.$destroy();
 }
});

输出结果为:

Vue.js 作为数据驱动视图的框架,我们首先要知道的就是如何将数据在视图中展示出来,传统的Web项目中,这一过程往往是通过后端模板引擎来进行数据和视图的渲染,例如PHP的smarty,Java的velocity和freemarker。但这样导致的情况是前后端语法会交杂在一起,前端HTML文件中需要包含后端模板引擎的语法,而且渲染完成后如果需要再次修改视图,就只能通过获取DOM的方法进行修改,并手动维持数据和视图的一致。而Vue.js的核心是一个响应式的数据绑定系统,建立绑定后,DOM将和数据保持同步,这样就无需手动维护DOM,使代码能够更加简洁易懂、提升效率。

本小节主要介绍Vue.js的数据绑定语法,出现的例子会基于以下js代码:

var vm = new Vue({
  el : '#app',
  data: {
   id : 1,
   index : 0,
   name : 'Vue',
   avatar : 'http://……'
   count : [1, 2, 3, 4, 5],
   names : ['Vue1.0', 'Vue2.0'],
   items : [
    { name : 'Vue1.0', version : '1.0' },
    { name : 'Vue1.1', version : '1.0' }
   ]
  }
});

1.文本插值

数据绑定最基础的形式就是文本插值,使用的是双大括号标签{{}},为“Mustache”语法(源自前端模板引擎Mustache.js),示例如下:

<span>Hello {{ name }}</span> // -> Hello Vue

Vue.js实例vm中name属性的值将会替换Mustache标签中的name,并且修改数据对象中的name属性,DOM也会随之更新。在浏览器console中运行 vm.name = 'Vue 1.0', 输出结果为Hello Vue 1.0。

模板语法同时也支持单次插值,即首次赋值后再更改vm实例属性值不会引起DOM变化, 例如以下模板在运行vm.name = 'Vue 1.0'后,依旧会输出Hello Vue:

<span>Hello {{* name }} </span> // -> Hello Vue

Vue.js 2.0去除了{{*}}这种写法,采用v-once代替。以上模板需要改写为<span v- once=”name”>{{name}}</span>。

2.HTML属性

Mustache标签也同样适用于HTML属性中,例如:

<div id="id-{{id}}"></div> // <div id="id-1"></div>

Vue.js 2.0 中废弃了这种写法,用v-bind指令代替,<div v-bind:id="'id-' + id"/></div> 代替,或简写为<div :id="'id-' + id"></div>

3.绑定表达式

放在 Mustache 标签内的文本内容称为绑定表达式。除了直接输出属性值之外,一段绑定表达式可以由一个简单的 JavaScript 表达式和可选的一个或多个过滤器构成。例如:

{{ index + 1 }} // 1
{{ index == 0 ? 'a' : 'b'}} // a
{{ name.split('').join('|') }} // V|u|e

每个绑定中只能包含单个表达式,并不支持JavaScript语句,否则Vue.js就会抛出warning异常。并且绑定表达式里不支持正则表达式,如果需要进行复杂的转换,可以使用过滤器或者计算属性来进行处理,以下的例子即为无效的表达式:

{{ var a = 1 }}  // 无效
{{ if (ok) { return name } }} // 无效,但可以写成 ok ? name : '' 或者 ok && name这样的写法

Vue.js 绑定表达式warning:

4.过滤器

Vue.js 允许在表达式后添加可选的过滤器,以管道符“|”指示。示例:

{{ name | uppercase }} // VUE

Vue.js 将name的值传入给uppercase这个内置的过滤器中(本质是一个函数),返回字符串的大写值。同时也允许多个过滤器链式使用,例如:

{{ name | filterA | filterB }}

也允许传入多个参数,例如:

{{ name | filterA arg1 arg2}}

此时,filterA将name的值做为第一个参数,arg1,arg2做为第二、第三个参数传入过滤器函数中。最终函数的返回值即为输出结果。arg1,arg2可以使用表达式,也可以加上单引号,直接传入字符串。例如:

{{ name.split('') | limitBy 3 1 }} // ->u,e

过滤器limitBy可以接受两个参数,第一个参数是设置显示个数,第二个参数为可选,指从开始元素的数组下标。

Vue.js 内置了10个过滤器,下面简单介绍它们的功能和用法。

① capitalize:字符串首字符转化成大写

② uppercase:字符串转化成大写

③ lowercase:字符串转化成小写

④ currency 参数为{String}[货币符号] ,{Number} [小数位],将数字转化成货币符号,并且会自动添加数字分节号。例如:

{{ amount | currency '¥' 2 }} // -> 若amount值为10000,则输出¥10,000.00

⑤ pluralize 参数为{String} single, [double, triple],字符串复数化。如果接收的是一个参数,那复数形式就是在字符串末尾直接加一个“s”。如果接收多个参数,则会被当成数组处理,字符串会添加对应数组下标的值。如果字符串的个数多于参数个数,多出部分会都添加最后一个参数的值。例如:

<p v-for="c in count">{{ c | pluralize 'item' }}  {{ c | pluralize 'st' 'nd' 'rd' 'th' }}</p>

输出结果:

⑥ json 参数为{Number}[indent]空格缩进数,与JSON.stringify()作用相同,将json对象数据输出成符合json格式的字符串。

⑦ debounce 传入值必须是函数,参数可选,为{Number}[wait],即延时时长。作用是当调用函数n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。例如:

<input v-on:keyup ="onKeyup | debounce 500"> // input元素上监听了keyup事件,并且延迟500ms触发

⑧ limitBy 传入值必须是数组,参数为{Number}limit,{Number}[offset], limit为显示个数,offset为开始显示数组下标。例如:

<div v-for="item in items | limitBy 10"></div> // items为数组,且只显示数组中的前十个元素

⑨ filterBy 传入值必须是数组,参数为{String | Function} targetStringOrFunction,即需要匹配的字符串或函数(通过函数返回值为true或false来判断匹配结果);“in” (可选分隔符);{String}[…searchKeys],为检索的属性区域。示例:

<p v-for="name in names | filterBy '1.0'">{{name}}</p> // 检索items数组中值包含1.0的元素
<p v-for="item in items | filterBy '1.0' in 'name'">{{ item | json}}</p> // 检索items数组中元素属性name值为1.0的元素输出。检索区域也可以为数组,即in [name, version],在多个属性中进行检索

上述两个例子的输出结果为:

<p v-for="item in items | filterBy customFilter">{{ item | json}}</p> // 使用自定义的过滤函数,函数可以在选项methods中定义
methods : {
  customFilter : function(item) {
   if(item.name) return true // 检索所有元素中包含name属性的元素
 }
}

⑩ orderBy 传入值必须是数组,参数为{String|Array|Function}sortKeys,即指定排序策略。这里可以使用单个键名,也可以传入包含多个排序键名的数组。也可以像Array.Sort()那样传入自己的排序策略函数。第二个参数为可选参数{String}[order],即选择升序或降序,order>=0为升序,order<0为降序。下面以三种不同的参数例子来说明具体的用法:

单个键名:<p v-for="item in items | orderBy 'name' -1">{{item.name}}</p> // items数组中以键名name进行降序排列
多个键名:<p v-for="item in items | orderBy [name,version] ">{{item.name}}</p> //使用items里的两个键名进行排序
自定义排序函数: <p v-for="item in items | orderBy customOrder">{{item.name}}  
</p> 
methods: {
 customOrder: function (a, b) {
   return parseFloat(a.version) > parseFloat(b.version) // 对比item中version的值的大小进行排序
 }
}

需要注意的是,Vue.js 2.0中已经去除了内置的过滤器,但也不用担心,我们会在第4章中详细说明过滤器的用法,以及如何声明自定义过滤器。而且Vue.js 的社区中本身就有优秀的开源过滤器,比如处理时间的moment.js,和货币格式化处理的account.js,我们会在第8章中说明如何使用Vue.js的插件。

5.指令

Vue.js也提供指令(Directives)这一概念,可以理解为当表达式的值发生改变时,会有些特殊行为作用到绑定的DOM上。指令通常会直接书写在模板的HTML元素中,而为了有别于普通的属性,Vue.js指令是带有前缀的v-的属性。写法上来说,指令的值限定为绑定表达式,所以上述提到的 JavaScript 表达式及过滤器规则在这里也适用。本书会在第3章中详细讲述指令及自定义指令的作用。本节先简单介绍指令绑定数据和事件的语法。

① 参数

<img v-bind:src="avatar" />

指令v-bind可以在后面带一个参数,用冒号(:)隔开,src即为参数。此时img标签中的src会与vm实例中的avatar绑定,等同于:

<img src="{{avatar}}" />

② 修饰符

修饰符(Modifiers)是以半角句号.开始的特殊后缀,用于表示指令应该以特殊方式绑定。

<button v-on:click.stop="doClick"></button>

v-on的作用是在对应的DOM元素上绑定事件监听器,doClick为函数名,而stop即为修饰符,作用是停止冒泡,相当于调用了e. stopPropagation()。

在项目开发中,我们展示的数据往往需要经过一些处理。除了在模板中绑定表达式或者利用过滤器外,Vue.js还提供了计算属性这种方法,避免在模板中加入过重的业务逻辑,保证模板的结构清晰和可维护性。

1.基础例子

var vm = new Vue({
  el : '#app,
  data: {
   firstName : 'Gavin',
   lastName: 'CLY'
  }
  computed : {
   fullName : function() {
    // this 指向vm实例
    return this.firstName + ' ' + this.lastName
   }
  }
});

<p>{{ firstName }}</p> // Gavin
<p>{{ lastName }}</p> // CLY
<p>{{ fullName }}</p> // Gavin CLY

此时,你对vm.firstName和vm.lastName进行修改,始终会影响vm.fullName。

2.Setter

如果说上面那个例子并没有体现出来计算属性的优势的话,那计算属性的Setter方法,则在更新属性时给我们带来了便利。示例:

var vm = new Vue({
  el : '#el',
  data: {
   cents : 100,
  }
  computed : {
   price : {
     set : function(newValue) {
      this.cents = newValue * 100;
     },
     get : function() {
      return (this.cents / 100).toFixed(2);
     }
   }
  }
});

在处理商品价格的时候,后端往往会把价钱定义成以分为单位的整型,避免在处理浮点类型数据时产生的问题。而前端则需要把价钱再转成元进行展示,而且如果需要对价钱进行修改的话,则又要把输入的价格再恢复到分传给后端,很是繁琐。

而在使用Vue.js的计算属性后,我们可以将vm.cents 设置为后端所存的数据,计算属性price为前端展示和更新的数据。

<p>&yen;{{price}}</p> // ¥1.00

此时更改vm.price = 2,vm.cents会被更新为200,在传递给后端时无需再手动转化一遍数据。

Vue.js 中提供v-model的指令对表单元素进行双向数据绑定,在修改表单元素值的同时,实例vm中对应的属性值也同时更新,反之亦然。本小节会介绍主要input元素绑定v-model后的具体用法和处理方式,示例所依赖的js代码如下:

var vm = new Vue({
 el : '#app',
 data: {
   message : '',
   gender : '',
   checked : '',
   multiChecked : [],
   selected : '',
   multiSelected : []
  a:'checked',
  b:'checked',
 }
});

1.Text

输入框示例,用户输入的内容和vm.message直接绑定:

<input type="text" v-model="message" />
<span>Your input is : {{ message }}</span>

2.Radio

单选框示例:

<label><input type="radio" value="male" v-model="gender ">男</lable>
<label><input type="radio" value="female" v-model="gender ">女</lable>
<p>{{ gender }}</p>

gender值即为选中的radio元素的value值。

3.Checkbox

Checkbox分两种情况:单个勾选框和多个勾选框。

单个勾选框,v-model即为布尔值,此时input的value并不影响v-model的值。

<input type="checkbox" v-model="checked" />
<span>checked : {{ checked }}</span>

多个勾选框,v-model使用相同的属性名称,且属性为数组。

<label><input type="checkbox" value="1" v-model=" multiChecked">1</lable>
<label><input type="checkbox" value="2" v-model=" multiChecked">2</lable>
<label><input type="checkbox" value="3" v-model=" multiChecked">3</lable>
<p>MultiChecked: {{ multiChecked.join('|') }}</p>

4.Select

同Checkbox元素一样,Select也分单选和多选两种,多选的时候也需要绑定到一个数组。

单选:

<select v-model="selected">
  <option selected>A</option>
  <option>B</option>
  <option>C</option>
</select>
<span>Selected: {{ selected }}</span>

多选:

<select v-model="multiSelected" multiple>
  <option selected>A</option>
  <option>B</option>
  <option>C</option>
</select>
<br>
<span>MultiSelected: {{ multiSelected.join('|') }}</span>

5.绑定value

表单控件的值同样可以绑定在Vue实例的动态属性上,用v-bind实现。示例:

1.Checkbox

<input type="checkbox" v-model="checked" v-bind:true-value="a" v-bind:false-value="b">

选中:vm.checked == vm.a  // -> true

未选中:vm.checked == vm.b // -> true

2.Radio

<input type="radio" v-model="checked" v-bind:value="a">

选中: vm.checked == vm.a // -> true

3.Select Options

<select v-model="selected">

  <!-- 对象字面量 -->

  <option v-bind:value="{ number: 123 }">123</option>

</select>

选中:

typeof vm.selected // -> 'object'

vm.selected.number // -> 123

6.参数特性

Vue.js为表单控件提供了一些参数,方便处理某些常规操作。

① lazy

默认情况下,v-model 在input 事件中同步输入框值与数据,加lazy属性后会在 change 事件中同步。

<input v-model="query" lazy />

② number

会自动将用户输入转为Number类型,如果原值转换结果为NaN则返回原值。

<input v-model="age" number/>

③ debounce

debounce为设置的最小延时,单位为ms,即为单位时间内仅执行一次数据更新。该参数往往应用在高耗操作上,例如在更新时发出ajax请求返回提示信息。

<input v-model="query" debounce="500" />

不过Vue.js 2.0中取消了lazy和number作为参数,用修饰符(modifier)来代替:

<input v-model.lazy="query" /> <input v-model.number="age" />

新增了trim修饰符,去掉输入值首尾空格:

<input v-model.trim="name" />

去除了debounce这个参数,原因是无法监测到输入新数据,但尚未同步到vm实例属性时这个状态。如果仍有需要,官方提供了手动实现的例子https://jsbin.com/zefawu/3/edit?html,output

在开发过程中,我们经常会遇到动态添加类名或直接修改内联样式(例如tab切换)。class和style都是DOM元素的attribute,我们当然可以直接使用v-bind对这两个属性进行数据绑定,例如<p v-bind:style='style'><p>,然后通过修改vm.style的值对元素样式进行修改。但这样未免过于繁琐而且容易出错,所以Vue.js为这两个属性单独做了增强处理,表达式的结果类型除了字符串之外,还可以是对象和数组。本小节就会对这两个属性具体的用法进行说明。

1.Class绑定

首先说明的是class属性,我们绑定的数据可以是对象和数组,具体的语法如下:

① 对象语法:v-bind:class接受参数是一个对象,而且可以与普通的class属性共存。

<div class="tab" v-bind:class="{'active' : active , 'unactive' : !active}">  
</div>
vm实例中需要包含
  data : {
   active : true
 }

渲染结果为: <div class="tab active"></div>

② 数组语法:v-bind:class也接受数组作为参数。

<div v-bind:class="[classA, classB]"></div>
vm实例中需要包含
  data : {
   classA : 'class-a',
   classB : 'class-b'
  }

渲染结果为:<div class="class-a class-b"></div>。

也可以使用三元表达式切换数组中的class,<div v-bind:class="[classA, isB ? classB : '']"></div>。如果vm.isB = false, 则渲染结果为<div v-bind:class="class-a"></div>。

2.内联样式绑定

style属性绑定的数据即为内联样式,同样具有对象和数组两种形式:

① 对象语法:直接绑定符合样式格式的对象。

<div v-bind:style="alertStyle"></div>
data : {
  alertStyle : {
   color : 'red',
   fontSize : '20px'
  }
}

除了直接绑定对象外,也可以绑定单个属性或直接使用字符串。

<div v-bind:style="{ fontSize : alertStyle.fontSize, color : 'red'}"></div>

② 数组语法:v-bind:style 允许将多个样式对象绑定到统一元素上。

<div v-bind:style="[ styleObjectA, styleObjectB]" .></div>

3.自动添加前缀

在使用transform这类属性时,v-bind:style会根据需要自动添加厂商前缀。:style在运行时进行前缀探测,如果浏览器版本本身就支持不加前缀的css属性,那就不会添加。

当获取到后端数据后,我们会把它按照一定的规则加载到写好的模板中,输出成在浏览器中显示的HTML,这个过程就称之为渲染。而Vue.js是在前端(即浏览器内)进行的模板渲染。本节主要介绍Vue.js渲染的基本语法。

早期的Web项目一般是在服务器端进行渲染,服务器进程从数据库获取数据后,利用后端模板引擎,甚至于直接在HTML模板中嵌入后端语言(例如JSP),将数据加载进来生成HTML,然后通过网络传输到用户的浏览器中,然后被浏览器解析成可见的页面。而前端渲染则是在浏览器里利用JS把数据和HTML模板进行组合。两种方式各有自己的优缺点,需要根据自己的业务场景来选择技术方案。

前端渲染的优点在于:

① 业务分离,后端只需要提供数据接口,前端在开发时也不需要部署对应的后端环境,通过一些代理服务器工具就能远程获取后端数据进行开发,能够提升开发效率。

② 计算量转移,原本需要后端渲染的任务转移给了前端,减轻了服务器的压力。

而后端渲染的优点在于:

① 对搜索引擎友好。

② 首页加载时间短,后端渲染加载完成后就直接显示HTML,但前端渲染在加载完成后还需要有段js渲染的时间。

Vue.js 2.0 开始支持服务端渲染,从而让开发者在使用上有了更多的选择。

Vue.js 提供v-if,v-show,v-else,v-for这几个指令来说明模板和数据间的逻辑关系,这基本就构成了模板引擎的主要部分。下面将详细说明这几个指令的用法和场景。

1.v-if/v-else

v-if和v-else的作用是根据数据值来判断是否输出该DOM元素,以及包含的子元素。例如:

<div v-if="yes">yes</div>

如果当前vm实例中包含data.yes = true,则模板引擎将会编译这个DOM节点,输出<div>yes</div>。

我们也可以利用v-else来配合v-if使用。例如:

<div v-if="yes">yes</div>
<div v-else>no</div>

需要注意的是,v-else必须紧跟v-if,不然该指令不起作用。例如:

<div v-if="yes">yes</div>
<p>the v-else div shows</p>
<div v-else>no</div>

最终这三个元素都会输出显示在浏览器中。

v-if绑定的元素包含子元素则不影响和v-else的使用。例如:

<div v-if="yes">
  <div v-if="inner">inner</div>
  <div v-else>not inner</div>
</div>
<div v-else>no</div>
new Vue({
  data : {
   yes : true,
   inner : false
  }
})

输出结果为:

<div>
  <div>not inner</div>
</div>

2.v-show

除了v-if,v-show也是可以根据条件展示元素的一种指令。例如:

<div v-show="show">show</div>

也可以搭配v-else使用,用法和v-if一致。例如:

<div v-show="show">show</div>
<div v-else>hidden</div>

与v-if不同的是,使用v-show元素,无论绑定值为true或false,均会渲染并保持在DOM中。绑定值的改变只会切换元素的css属性display。例如:

<div v-if="show">if</div>
<div v-show="show">show</div>

show分别为true时的结果:

show分别为false时的结果:

3.v-if vs v-show

从上述v-show图能够明显看到,当v-if和v-show的条件发生变化时,v-if引起了dom操作级别的变化,而v-show仅发生了样式的变化,从切换的角度考虑,v-show消耗的性能要比v-if小。

除此之外, v-if切换时,Vue.js会有一个局部编译/卸载的过程,因为v-if中的模板也可能包括数据绑定或子组件。v-if会确保条件块在切换当中适当地销毁与中间内部的事件监听器和子组件。而且v-if是惰性的,如果在初始条件为假时,v-if本身什么都不会做,而v-show则仍会进行正常的操作,然后把css样式设置为display:none。

所以,总的来说,v-if有更高的切换消耗而v-show有更高的初始渲染消耗,我们需要根据实际的使用场景来选择合适的指令。

v-for指令主要用于列表渲染,将根据接收到数组重复渲染v-for绑定到的DOM元素及内部的子元素,并且可以通过设置别名的方式,获取数组内数据渲染到节点中。例如:

<ul>
  <li v-for="item in items">
   <h3>{{item.title}}</h3>
   <p>{{item.description}}</p>
  </li>
</ul>
var vm = new Vue({
  el : '#app',
  data: {
   items : [
    { title : 'title-1', description : 'description-1'},
    { title : 'title-2', description : 'description-2'},
    { title : 'title-3', description : 'description-3'},
    { title : 'title-4', description : 'description-4'}
   ]
  }
});

其中items为data中的属性名,item为别名,可以通过item来获取当前数组遍历的每个元素,输出结果为:

<ul>
  <li>
   <h3>title-1</h3>
   <p>description-1</p>
  </li><li>
   <h3>title-2</h3>
   <p>description-2</p>
  </li><li>
   <h3>title-3</h3>
   <p>description-3</p>
  </li><li>
   <h3>title-4</h3>
   <p>description-4</p>
  </li>
</ul>

v-for内置了$index变量,可以在v-for指令内调用,输出当前数组元素的索引。另外,我们也可以自己指定索引的别名,如<li v-for="(index,item) in items">{{index}} – {{$index}} – {{item.title}}</li>,输出结果为:

<ul>
  <li>
   0 - 0 - title-1
  </li><li>
   1 - 1 - title-2
  </li><li>
   2 - 2 - title-3
  </li><li>
   3 - 3 - title-4
  </li>
</ul>

需要注意的是Vue.js对data中数组的原生方法进行了封装,所以在改变数组时能触发视图更新,但以下两种情况是无法触发视图更新的:

① 通过索引直接修改数组元素, 例如 vm.items[0] = { title : 'title-changed'};

② 无法直接修改“修改数组”的长度, 例如:vm.items.length = 0

对于第一种情况,Vue.js提供了$set方法,在修改数据的同时进行视图更新,可以写成:

vm.items.$set(0, { title : 'title-changed'} 或者vm.$set('items[0]', { title : 'title- also-changed '}), 这两种方式皆可以达到效果。

在列表渲染的时候,有个性能方面的小技巧,如果数组中有唯一标识id,例如:

items : [
  { _id : 1, title : 'title-1'},
  { _id : 2, title : 'title-2'},
  { _id : 3, title : 'title-3'}
  …
]

通过trace-by给数组设定唯一标识,我们将上述v-for作用于的li元素修改为:

<li v-for="item in items" track-by="_id"></li>

这样,Vue.js在渲染过程中会尽量复用原有对象的作用域及DOM元素。

v-for除了可以遍历数组外,也可以遍历对象,与$index类似,作用域内可以访问另一内置变量$key,也可以使用(key, value)形式自定义key变量。

<li v-for="(key, value) in objectDemo">
  {{key}} - {{$key}} : {{value}}
</li>
var vm = new Vue({
  el : '#app',
  data: {
   objectDemo : {
    a : 'a-value',
    b : 'b-value',
    c : 'c-value',
   }
  }
});

输出结果:

最后,v-for还可以接受单个整数,用作循环次数:

<li v-for="n in 5">
  {{ n }}
</li>

输出结果:

上述的例子中,v-show和v-if指令都包含在一个根元素中,那是否有方式可以将指令作用到多个兄弟DOM元素上?Vue.js提供了template标签,我们可以将指令作用到这个标签上,但最后的渲染结果里不会有它。例如:

<template v-if="yes">
 <p>There is first dom</p>
 <p>There is second dom</p>
 <p>There is third dom</p>
</template>

输出结果为:

同样, template标签也支持使用v-for指令,用来渲染同级的多个兄弟元素。例如:

<template v-for="item in items">
 <p>{{item.name}}</p>
 <p>{{item.desc}}<p>
</template>

当模板渲染完成之后,就可以进行事件的绑定与监听了。Vue.js提供了v-on指令用来监听DOM事件,通常在模板内直接使用,而不像传统方式在js中获取DOM元素,然后绑定事件。例如:

<button v-on:click="say">Say</button>

通过v-on可以绑定实例选项属性methods中的方法作为事件的处理器,v-on:后参数接受所有的原生事件名称。例如:

<button v-on:click="say">Say</button>
var vm = new Vue({
 el : '#app',
 data: {
  msg : 'Hello Vue.js'
 },
 methods : {
  say : function() {
    alert(this.msg);
  }
 }
});

单击button,即可触发say函数,弹出alert框'Hello Vue.js'。

Vue.js 也提供了v-on的缩写形式,我们可以将模板中的内容改写为<button @click='say'>Say</button>,这两句语句是等价的。

除了直接绑定methods函数外,v-on也支持内联JavaScript语句,但仅限一个语句。例如:

<button v-on:click="sayFrom ('from param')">Say</button>
var vm = new Vue({
 el : '#app',
 data: {
  msg : 'Hello Vue.js'
 },
 methods : {
  sayFrom: function(from) {
   alert(this.msg + '' + from);
  }
 }
});

在直接绑定methods函数和内联JavaScript语句时,都有可能需要获取原生DOM事件对象,以下两种方式都可以获取:

<button v-on:click="showEvent">Event</button>
<button v-on:click="showEvent($event)">showEvent</button>
<button v-on:click="showEvent()">showEvent</button> // 这样写获取不到event
var vm = new Vue({
 el : '#app',
 methods : {
  showEvent : function(event) {
  console.log(event);
  }
 }
});

同一元素上也可以通过v-on绑定多个相同事件函数,执行顺序为顺序执行,例如:

<div v-on:click="sayFrom('first')" v-on:click ="sayFrom('second)">

Vue.js为指令v-on提供了多个修饰符,方便我们处理一些DOM事件的细节,并且修饰符可以串联使用。主要的修饰符如下。

.stop: 等同于调用event. stopPropagation()。

.prevent: 等同于调用event.preventDefault()。

.capture: 使用capture模式添加事件监听器。

.self: 只当事件是从监听元素本身触发时才触发回调。

使用方式如下:

<a v-on:click.stop='doThis'></a>
<form v-on:submit.prevent="onSubmit"></form> // 阻止表单默认提交事件
<form v-on:submit.stop.prevent="onSubmit"></form> // 阻止默认提交事件且阻止冒泡
<form v-on:submit.stop.prevent></form> // 也可以只有修饰符,并不绑定事件

可以尝试运行以下这个例子,更好地理解修饰符在其中起到的作用。

var vm = new Vue({
 el : '#app',
 methods : {
  saySelf(msg) {
  alert(msg);
  }
 }
});
<div v-on:click="saySelf('click from inner')" v-on:click.self="saySelf('click from self')">
 <button v-on:click="saySelf('button click')">button</button>
 <button v-on:click.stop="saySelf('just button click')">button</button>
</div>

除了事件修饰符之外,v-on还提供了按键修饰符,方便我们监听键盘事件中的按键。例如:

<input v-on:keyup.13="submit"/> // 监听input的输入,当输入回车时触发Submit函数(回车的keycode值为13),用于处理常见的用户输入完直接按回车键提交)

Vue.js给一些常用的按键名提供了别称,这样就省去了一些记keyCode的事件。全部按键别名为:enter、tab、delete、esc、space、up、down、left、right。例如:

<input v-on:keyup.enter="submit" />

Vue.js也允许我们自己定义按键别名,例如:

Vue.directive('on').keyCodes.f1 = 112; // 即可以使用<input v-on:keyup.f1="help" />

Vue.js 2.0 中可以直接在Vue.config.keyCodes里添加自定义按键别名,无需修改v-on指令,例如:

Vue.config.keyCodes.f1 = 12。

如果你之前没有接触过Angularjs、ReactJS这类框架,或许会对Vue.js这种事件监听方式感到困惑。毕竟我们一开始接受的理念就是将HTML和JS隔离开编写。但其实Vue.js事件处理方法和表达式都严格绑定在当前视图的ViewModel上,所以并不会导致维护困难。

而这么写的好处在于:

① 无需手动管理事件。ViewModal被销毁时,所有的事件处理器都会自动被删除,让我们从获取DOM绑定事件然后在特定情况下再解绑这样的事情中解脱出来。

② 解耦。ViewModal代码是纯粹的逻辑代码,和DOM无关,有利于我们写自动化测试用例。

还有个与以往不同的细节是,我们在处理ul、li这种列表,尤其是下拉刷新这种需要异步加载数据的列表时,往往会把li事件代理到ul上,这样异步加载进来的新数据就不需要再次绑定事件。而Vue.js这类的框架由于不需要手动添加事件,往往直接会把事件绑定在li上,类似这样:<li v-repeat="item in items" v-on:click="clickLi"></li>,理论上每次新增li的时候都会进行同li个数的事件绑定,比用事件代理多耗了些性能。但在实际运用中并没有什么特别的性能瓶颈影响,而且我们也省去在代理中处理e.target的步骤,让事件和DOM元素关系更紧密、简单。

组件化开发也是Vue.js中非常重要的一个特性,我们可以将一个页面看成一个大的根组件,里面包含的元素就是不同的子组件,子组件也可以在不同的根组件里被调用。在上述例子中,可以看到在一个页面中通常会声明一个Vue的实例new Vue({})作为根组件,那么如何生成可被重复使用的子组件呢?Vue.js提供了Vue.extend(options)方法,创建基础Vue构造器的“子类”,参数options对象和直接声明Vue实例参数对象基本一致,使用方法如下:

var Child = Vue.extend({
 template : '#child',
 // 不同的是,el和data选项需要通过函数返回值赋值,避免多个组件实例共用一个数据
 data : function() {
  return {
   ….
  }
 }
 ….
})
Vue.component('child', Child) // 全局注册子组件
<child ….></child> // 子组件在其他组件内的调用方式

更多组件的使用方法将会在第6章中进行详细的说明。


相关图书

TypeScript全栈开发
TypeScript全栈开发
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Vue.js全平台前端实战
Vue.js全平台前端实战
Flutter内核源码剖析
Flutter内核源码剖析
智能前端技术与实践
智能前端技术与实践
从0到1:ES6快速上手
从0到1:ES6快速上手

相关文章

相关课程