Vue.js 项目实战

Vue 开发入门

Vue 是一个专注于构建 Web 用户界面JavaScript 库。

1.1 为什么需要另外一个前端框架

Vue 易用、灵活、速度快、还提供了许多功能和可选工具,这使得开发者能够快速地构建一个现代 web 应用。Vue 的作者尤雨溪将其称为渐进式框架

  • Vue 遵循渐进增量的设计原则,其核心库专注于用户界面,使得现有的项目可以方便地集成使用 Vue。
  • Vue 既可以构建出很小的原型,又可以构建出复杂的大型 web 应用。
  • Vue 非常容易上手 —— 初学者能轻松掌握 vue,而已经熟悉 Vue 的开发者则可以在实际项目中快速发挥出它的作用。

Vue 整体上遵循 MVVM(Model-View-ViewModel,模型 - 视图 -视图模型)架构,也就是说 View(用户界面或视图)和 Model(数据)是独立的,ViewModel(Vue)是 View 和 Model 交互的桥梁。Vue 对 View 和 Model 之间的更新操作做了自动化处理,并且已经为开发者进行了优化。

Vue 还吸收了其他类似框架( 如 React、Angular、Polymer)的精华。

Vue 核心功能概述

  • 一个响应式的数据系统,能通过轻量级的虚拟 DOM 引擎和最少的优化工作来自动更新用户界面。
  • 灵活的视图声明,包括优雅友好的 HTML 模板、JSX(在 JavaScript 中编写 HTML 的技术)以及 hyperscript 渲染函数(完全使用 JavaScript )。
  • 由可维护、可复用组件组成的组件化用户界面。
  • 官方的组件库提供了路由、状态管理、脚手架以及更多高级功能,使 Vue 成为了一个灵活且功能完善的前端框架。

Weex、NativeScript

1.1.2 兼容性需求

Vue 不支持 Internet Explorer 8 以下版本,因为 Vue 使用了 JavaScript 中相对较新的特性,比如 Object.defineProperty,
而它们在老版本的浏览器中是无法 polyfill 的。

编译器 Babel ,它编译过的代码可以很好地运行在老版本浏览器中。

1.3 创建一个应用

整个库都是基于 Vue 实例的,而实例是 View 和 Model(数据)交互的桥梁。因此需要创建一个新的 Vue 实例来启动应用。

1
2
3
4
5
6
7
8
9
10
11
//  创建 Vue 实例
var app = new Vue({
// 根 DOM 元素的 CSS 选择器
el: '#root',
// 一些数据
data(){
return {
message: 'Hello Vue.js'
}
}
})

使用关键字 new 调用 Vue 构造器创建了一个新的实例。Vue 构造器有一个参数 —— option 对象。该参数可以携带多个属性(称为选项)。

通过 el 选项,我们使用 CSS 选择器告知 Vue 将实例添加(挂载)到 Web 页面的哪个 DOM 元素中。
也可以 Vue 实例的 $mount 的方法代替el选项:
app.$mount(‘#root’)。

1
2
3
4
5
6
7
8
9
var app = new Vue({
data(){
return {
message: 'Hello Vue.js'
}
}
})
// 添加 Vue 实例到页面中
app.$mount("#root");

Vue 实例的大多数特殊方法和属性都是以美元符号($)开头的。

在单个 Web 页面中,开发者可以添加任意多个 Vue 应用。只需要为每个应用创建出
新的 Vue 实例并挂载到不同的 DOM 元素即可。当想要将 Vue 集成到已有的项目中时,这非常方便。

Vue 开发者工具

Vue 有一个官方调试工具,在 Chrome 中以扩展的方式呈现,名为 Vue.js devtools。通过该工具可以看到应用的运行情况,这有助于调试代码
。可以在 Chrome 网上应用商品下载;如果使用 Firefox,则可以到 Firefox 附加组件 下载。
使用 Chrome 版本的话,还需要进行额外的设置。在扩展设置中,启用 Allow access to file URLs 选项。这样调试工具就能在从本地磁盘打开的 Web 页面上检测 Vue 了。

可以将 devtools 选项卡拖放到喜欢的位置。建议将其放在靠前的位置,因为当 Vue 不处于开发模式或没有运行时,该选项卡在页面中是隐藏起来的

可以通过 name 选项修改 Vue 实例的名字:

1
2
3
4
var app = new Vue({
name : 'MyApp',
// ...
})

当一个页面中有多个 Vue 实例时,这有助于直观地在开发者工具中找到具体的某个实例。

1.4 借助模板实现 DOM 的动态性

模板是描述 View 最简单的方法,只需要少量额外的语法就能轻松实现 DOM 的动态更新。

1.4.1 文本显示

文本插值用于在 Web 页面中显示动态的文本。文本插值的语法是在双花括号内包含单个任意类型的 JavaScript 表达式。当 Vue 处理模板时,该 JavaScript 表达式的结果将会替换掉双花括号标签。

1
2
3
<div id="root">
{{ message }}
</div>

DOM 和 数据连通了

1
app.message = 'Awesome!'

数据绑定,每当数据有改变时, Vue 都能够自动更新 DOM,Vue 框架中包含一个非常强大且高效的响应系统,能对所有的数据进行跟踪,并且能在数据发生改变时按需自动更新 View。

1.4.2 利用指令添加基本的交互

Vue 中所有的指令命名都是带 V- 前缀的,并遵循短横线分隔式(kebab-case)语法。这个意味着要用短横线将单词分开。HTML 属性是不区分大小写的。

1
2
3
4
5
<div id="root">
<p>{{message}}}</p>
<!-- 添加一个文本输入框 -->
<input v-model = "message">
</div>

双向数据绑定 v-model

项目 1:Markdown 笔记

v-model 指令不限于文本输入使用。它同样可以用于其他元素,例如勾选框、单选按钮,甚至自定义组件。

2.1.3 预览面板

计算属性 通过它可以定义一个新的属性,而该属性可以结合任意多个属性,并做相关转换操作。

  • 计算属性的值基于它的依赖进行缓存,因此如果没有必要是不会重新运行函数的,从而有效防止无用计算;
  • 当函数中用到的某个属性发生了改变,计算属性的值也会根据需要自动更新;
  • 计算属性可以如其他普通属性一起使用(可以在其他计算属性中使用计算属性);
  • 计算属性只有真正用于应用中时,才会进行计算操作。
在应用内,不建议使用 v-html 指令对用户提供的内容做 HTML 插值。这是因为用户可能会在标签中编写不怀好意、会被执行的 JavaScript 代码。当然对普通文本做插值是安全的,因为 HTML 不会被执行。

元素中的任意内容将被 v-html 指令的值替代。可以利用这一点来放置占位符内容。

对于文本插值,v-text 是一个与 v-html 等效的指令。它的行为与 v-html 类似,只不过会对 HTML 标签做转译处理,形同典型的文本插值。

2.1.4 保存笔记

localStorage 保存笔记

侦听改变

监听器 watch 选项是一个字典,把被侦听属性的名字作为键,把侦听选项对象作为值。这个对象必须要一个 handler 属性,该属性可以是一个函数,也可以是一个方法的名字。这个处理函数将接收两个参数:被侦听属性的新值和旧值。

1
2
3
4
5
6
7
8
9
10
new Vue({
// 侦听 content 数据属性
watch: {
content: {
handler(val,oldVal){
console.log('new note:', val , 'old note' , oldVal)
}
}
}
})

还有另外两个选项可以和 handler 一起使用。

  • deep 是一个布尔类型,告诉 Vue 以递归的方式侦听嵌套内部值的变化。
  • immediate 也是一个布尔类型,会立即触发调用处理函数,而不用等到属性第一次变化时才调用。
这两个选项的默认值都是 false,所以不需要使用的时候,可以完全忽略它们。 当不需要其他选项(例如 deep 或 immediate)时,这是侦听器中最常用的语法。
1
2
3
4
watch: {
content(val,oldVal){
}
}

保存笔记

1
localStorage.setItem('content',val)

复用方法
良好的编程准则之一:不要重复自己(DRY),也称为一次仅且一次。开发者应该遵守这个准则。因此可以把一些逻辑写在
可复用的函数里面:methods。

1
2
3
4
5
6
7
8
9
10
11
12
new Vue({
watch:{
content: 'saveNote'
},
methods:{
saveNote(val){
console.log('saving note:',this.content);
localStorage.setItem('content',thie.content)
}
}
})

访问 Vue 实例

在 methods 内部,可以通过 this 关键字访问 Vue 实例,还可以访问 Vue 实例的其他属性或特殊函数。

基本上可以在任意函数(方法、处理函数或其他钩子)其中使用 this 关键字访问 Vue 实例。 生命周期钩子

生命周期钩子

每个 Vue 实例都严格遵守一个生命周期,包括多个环节:创建、挂载到页面、更新,最终被销毁。例如,在创建实例阶段,Vue 会将实例数据变成响应式数据。

钩子是一组特殊的函数,会在某个时间点被自动调用。这就允许我们自定义框架的逻辑。例如在创建 Vue 实例时调用一个方法。

在每个环节之中或之前,有很多钩子可以用于执行逻辑。

  • beforeCreate:在 Vue 实例被创建时(例如使用 new Vue({ }))、完成其他事项之前调用。
  • created:在实例准备就绪之后调用。注意,此时实例还没有挂载到 DOM 中。
  • beforeMount:在挂载(添加)实例到 web 页面之前调用。
  • mounted:在实例被挂载到页面并且 DOM 可见时调用。
  • beforeUpdate:当实例需要更新时(一般来说,是当某个数据或计算属性发生改变时)调用。
  • updated:在把数据变化应用到模板之后调用。注意此时 DOM 可能还没有更新。
  • beforeDestroy:在实例销毁之前调用。
  • destroyed:在实例完全销毁之后调用。
在 JavaScript 中,如果值为 false、0、空字符传、null、undefined 或 NaN(不是一个数),则它就是假值。在浏览器的本地存储数据中,如果对应的键不存在, localStorage.getItem() 方法会返回 null。

在数据中直接初始化

1
2
3
4
5
6
7
new Vue({
data(){
return{
content:localStorage.getItem('content') || 'You can write in **markdown**'
}
}
})

2.2 多条笔记

2.2.1 笔记列表

添加新建笔记的方法
每一条笔记都是具体如下数据的对象。

  • id :笔记的唯一标识符。
  • title :笔记的标题,用来显示在笔记列表中。
  • content : 笔记的 Markdown 格式内容。
  • created : 笔记创建的日期。
  • favorite : 这是一个布尔型,用于表示是否收藏了笔记,已收藏的笔记显示在笔记列表的顶部。

选择当前时间(也就是从 1970 年 1 月 1 日 00:00:00 UTC 开始经过的毫秒数)作为区分笔记的唯一标识符,这是一种不错的方式。

用 v-on 实现按钮的单击事件

1
<button v-on:click="addNote"></button>

绑定事件 v-on: 简写 @

1
<button @:click="addNote"></button>

用 v-bind 绑定属性

1
<button v-bind:title="notes.length + ' note(s) already'">

属性绑定 v-bind: 简写 :

1
<button :title="notes.length + ' note(s) already'">
当需要更新属性值的时候,用 v-bind 指令绑定的 JavaScript 表达式会自动重新运算。

用 v-for 显示列表

1
2
3
<div class="notes">
<div class="note" v-for="note of notes">{{note.title}}</div>
</div>

2.2.2 选择一条笔记

动态 CSS 类

1
<div :class= "{ one: note === selectedNote }"></div>
可以把静态与动态的 class 属性结合起来。建议将非动态的类放到静态的属性中,Vue 会对静态值做优化处理。

条件指令 v-if
v-else-if
v-else

标签不会出现在 DOM 中。用于对实际的元素进行重新组合。

侦听器默认值侦听目标对象的直接变化:赋值、数组添加、删除、移动。
例如:

1
2
3
4
5
6
7
8
9
//  赋值
this.selectedId = 'abcd'

// 在数组中添加或删除某项
this.selectedId.push({...})
this.selectedId.splice(index,1);

// 数组排序
this.notes.sore(...)

操作不会触发侦听器

1
2
3
4
5
6
//  给某个属性或者嵌套对象赋值
this.myObject.someAttribute = 'abcd';
this.myObject.nestedObject.otherAttribute = 42

// 修改数组中某项的内容
this.notes[0].content = 'new content'

这种情况下,需要在侦听器上添加 deep 选项

1
2
3
4
5
6
7
watch: {
notes: {
handle : 'saveNotes',
// 需要使用这个选项来监听数组中每个笔记属性的变化
deep: true
}
}

按照收藏、时间排序

1
2
3
4
5
6
7
computed: {
sortedNotes(){
return this.notes.slice()
.sort((a,b) => a.created - b.created)
.sort((a,b) => (a.favorite === b.favorite) ? 0 : a.favorite ? -1 : 1)
}
}
由于 sort 方法会直接修改源数组,这里使用 slice 方法创建新的副本。这样可以防止 notes 监听器。

创建日期过滤器

(1)引入 momentjs

1
<script src="https://unpkg.com/moment"></script>

(2) 使用 Vue.filter 全局方法(不在 Vue 实例的创建代码中,比如位于文件开头)注册过滤器

1
Vue.filter('date',time=> mement(time).format('DD/MM/YY, HH:mm'))
1
<span class="value">{{ selectedNote.created | date }}</span>

文本统计

1
2
3
4
5
6
7
8
9
10
11
12
//  计算换行符的格式 
str.split(/\r\.|\r|\n/).length
// 将换行符转换为空格
str.replace(/\n/g, '');
// 排除开头和结尾的空格
str.replace(/(^\s*)|(\s*$)/gi, '')
// 将多个重复空格转换为一个
str.replace(/\s\s+/gi, ' ');
// 返回空格数量
str.split(' ').length;
// 字符数量
str.split('').length

项目 2:城堡决斗游戏

在 Vue 实例构造器之后,添加一个事件监听器到 window 对象中,监听浏览器窗口大小的变化。

1
2
3
4
//  窗口大小变化的处理
window.addEventListener('resize', () => {
state.wordRatio = getWorldRatio();
}

3.3.3 万能的组件

组件是构建应用的基础模块,是 Vue 应用的核心概念。组件是视图的一个个小部分,因此相对来说应用比较小、可复用,并且尽可能地自给自足。采用组件构建应用有助于应用的维护和升级,特别是当应用规模变大之后。实际上,这已经成为了高效、可控地开发大型 Web 应用的标准方法。

组件

可以使用全局函数 Vue.component() 来注册组件。该函数接受两个参数:一个是注册组件的名称,另一个则是组件的定义对象本身,它与 Vue 实例使用相同的选项。

1
2
3
Vue.component('top-bar',{
template:`<div class='top-bar'>Top bar</div>`
})

使用 prop 进行父组件到子组件的通信

利用 props 选型可以将 prop 添加到组件中。

1
2
3
4
5
6
7
8
Vue.component('top-bar',{
props: ['players','currentPlayerIndex','turn'],
created(){
console.log(this.players);
}
})

<top-bar :turn="turn" :current-play-index="currentPlayIndex" :players="players">
注意:由于 HTML 是不区分大小写的,建议对 prop 的名字使用短航线命名方法(kebab-case),而在 JavaScript 代码中使用驼峰式命名方法(camel-case)。

模板中的 prop

通过 players prop 显示玩家姓名。

1
2
3
4
5
6
template:`
<div class="top-bar">
<div class="player p0">{{ players[0].name}}</div>
<div class="player p1">{{ players[1].name}}</div>
</div>
`

在组件上监听原生事件
为监听到组件的 click 事件,需要对 v-on 指令使用 .native 修饰符。

1
<card :def="testCard" @click.navtive="handlePlay">

使用自定义事件进行子组件到父组件的通信
在组件内部,使用 $emit 这个特殊方法触发的事件可以被父组件捕获到。该方法接收一个固定的参数,即事件类型:

1
this.$emit('play','orange',42)

可以使用名为 $on 的特殊方法监听自定义事件:

1
2
3
4
5
6
7
8
9
10
11
this.$on('play', () => {
console.log('Caught a play event!');
})

<card v-on:play="handlePlay"/>>
// 简写:
<card @play="handlePlay"/>

handlePlay(color,number){
console.log('handle play event','color = ' , color ,'number=',number)
}
Vue 的自定义事件与浏览器事件系统是完全分开的。方法 $on 和 $emit 并不是 addEventListener 和 dispatchEvent 的别名。这也解释了为什么在组建中需要使用 .native 修饰符来监听浏览器事件(如 click)。 大多数情况下,最好使用自定义事件完成组件之间的通信。

hand 组件的动画过度效果

动画效果:CSS 过渡结合 <transition> 组件。当添加或移除元素时,使用 v-if 或 v-show 指令来帮助实现 CSS 过渡。

1
2
3
4
5
//  应用状态集合
var state = {
// 用户界面
activeOverlay: null
}
1
2
3
<transition>
<hand v-if="!activeOverlay"/>
</transition>

<transition> 特殊组件不会显示在 DOM 中。

当元素被添加到 DOM 时(进入阶段),<transition> 组件会自动将下列 CSS 类应用到元素中。

v-enter-active: 当进入过渡状态被激活时,会应用该类。在元素插入 DOM 之前,添加该类到元素中,并在动画结束时移除它。应该在这类中添加一些 transition CSS 属性并定义其过渡时长。

v-enter: 元素进入过渡的开始状态。在元素插入 DOM 之前,添加该类到元素中,并在元素被插入的下一帧移除。例如,你可以在这个类中设置透明为 0。

v-enter-to: 元素进入过渡的结束状态。在元素插入 DOM 后的下一帧添加,同时 v-enter 被移除。当动画完成后,v-enter-to 会被移除。

当元素从 DOM 中移除时(离开阶段),<transition> 组件会自动将下列 CSS 类应用到元素中。

v-leave-active:当离开过渡状态被激活时,会应用该类。当离开过渡触发时,添加该类到元素中,并在从 DOM 中移除元素时移除它。应该在这个类中添加一些 transition CSS 属性并定义其过渡时长。

v-leave:元素被移除时的开始状态。当离开过渡触发时,添加该类到元素中,并在下一帧移除。

v-leave-to:元素离开过渡的结束状态。在离开过渡触发后的下一帧添加,同时 v-leave 被移除。当从 DOM 中移除元素时,该类也会被移除。

在离开阶段,并不会立即从 DOM 中移除元素。当过渡结束后,才会将其移除,这样用户可以看到动画效果。

进入 v-enter-active
v-enter v-enter-to
透明度0 -> 透明度1

离开 v-leave-active
v-leave v-leave-to
透明度1 -> 透明度0

<transition> 组件会自动检测应用在元素上的 CSS 过渡效果的持续时间。

复用动画

1
2
3
<transition name="fade">
<hand v-if="!activeOverlay" :cards="testHand">
</transition>
1
2
3
4
5
6
7
8
9
10
/* transition.css */
.fade-enter-active,
.fade-leave-acteve {
transition: opacity 1s;
}

.fade-enter,
.fade-leave-to {
opacity: 0;
}

现在只需要通过 <transition name="fade">标签就可以在任意元素上复用这个动画了。

贝塞尔曲线缓动函数,可以使得动画更加平滑。

1
2
3
4
5
6
7
8
9
10
.hand-enter-active .wrapper,
.hand-leave-active .wrapper {
transition: transform .8s cubic-bezier(.08,.74,.34,1);
transform-origin: bottom center;
}

.hand-enter .wrapper,
.hand-leave-to .wrapper {
transition: rotate(90deg);
}

为元素列表添加动画效果,需要使用另外一个特殊的组件 <transition-group>。当元素被添加、移除和移动时,该组件将对它的子元素做出动画效果。 跟 <transition> 元素不同的是,<transition-group>默认情况下会作为<span> 元素出现在 DOM 中。可以使用 tap prop 修改这个 HTML 元素。

1
2
3
<transition-group tag="ul">
<li v-for="item of items" />
</transition-group>

<transition-group> 的子元素必须由唯一的 key 做标识。

1
2
3
4
// 指定过渡效果名称为 card 
<transition-group name="card" tag="div" class="cards">
<card v-for="card of cards">
</transition-grou

特殊的 key 属性
当 Vue 更新存在于 v-for 循环中的 DOM 元素列表时,会尽量最小化应用于 DOM 的操作,例如添加和移除元素。大多数情况下,这是更新 DOM 的一种非常高效的方法,并且对性能的提升也有帮助。
为了做到这一点,Vue 会尽可能地复用元素,并仅对 DOM 中需修改的地方进行最小范围的修改,以达到理想的结果。这意味着重复的元素会被打包到一起,不会在添加或移除列表中的项时移动它们。不过,这也意味着对其应用过渡不会有动画效果。

key 属性为元素指定唯一标识符。

使用插槽分发内容

1
2
3
4
5
<div class="overlay" @click="handleClick">
<div class="content">
<slot />
</dvi>
</div>
1
2
3
<overlay>
Hello world!
</overlay>

Vue 提供了一个特殊的组件可以把其转换为任意的组件:component 组件。只需要将它的 is prop 设置为一个组件名或组件定义对象,甚至是一个 HTML 标签,component 组件就会变为响应的内容:

动态修改组件

1
2
3
<overlay v-if="activeOverlay">
<component :is="'overlay-content-'+activeOverlay" :player="currentPlayer" >
</overlay>

当 targetHeight 属性发生改变时,就开始播放动画

1
2
3
4
5
6
7
8
9
10
11
12
watch:{
targetHeight(newValue,oldValue){
const vm = this;
new TWEEN.Tween({value:oldValue})
.easing(TWEEN.Easing.Cubi.InOut)
.to({value: newValue},500)
.onUpdata(function(){
vm.height = this.value.toFixed(0)
})
.start()
}
}

高级项目设置

4.1 设置开发环境

安装 Node.js 和 npm

4.1.1 安装官方命令行工具 vue-cli

安装 vue-cli 并将其作为一个全局的包:

1
2
3
4
5
npm install -g vue-cli

// 打印 vue-cli 打印版本
vue -V
vue --version

项目脚手架

推荐的官方模板是 webpack 模板,具有使用 Vue 创建整个 SPA(单页面应用)所需的全部功能。使用 webpack-simple 并逐步引入功能。

渲染函数

Vue 使用一个虚拟 DOM 的实现,用树状结构的 JavaScript 对象来构建虚拟 DOM。然后 Vue 将虚拟 DOM 应用到真实浏览器的 DOM 上,所用方法是计算两者之间的差距。这尽可能地避免了 DOM 操作,因为 DOM 操作通常是主要的性能瓶颈。

按照惯例,h 是 createElement 的别名,这是编写 JSX 时非常常见和必须的。它得名于使用 JavaScript 描述 HTML 的技术 - Hyperscript。

createElement(或称 h)方法最多需要 3 个参数,
(1)第一个参数是元素类型。它可以是一个 HTML 标签名称(比如 div),在应用中注册过得组件名称,或者直接就是一个组件定义对象。
(2)第二个参数是可选的。它是一个定义了属性、prop、事件监听器等的数据对象。
(3)第三个参数也是可选的。它可以是简单的纯文本,也可以是一个用 h 创建的其他元素的数据。

示例:

1
2
3
4
5
6
7
8
9
10
11
render(h){
return h('ul',{'class':'movies'},[
h('li',{'class': 'movie'},'Start Wars'),
h('li',{'class':'movie'},'Blade Runner'),
])
}

<ul class='movies'>
<li class='movie'>Star Wars</li>
<li class='movie'>Blade Runner</li>
</ul>

4.2.4 配置 Babel

Babel 是一个 JavaScript 代码编辑工具,以便我们在旧版和最新版的浏览器中使用新特性(如 JSX 或箭头函数)。建议在所有正式的 JavaScript 项目中使用 Babel。

polyfill 是用于检查特性在浏览器中是否可用的代码;如果不可用,它将实现这个特性,使其可以像原生的一样工作。

1.Babel Vue 预览

安装并使用 babel-preset-vue

1
npm i -D babel-preset-vue

主要的 Babel 配置是在项目根目录下已存在的 .babelrc JSON 文件中完成的。

打开这个 .babelrc 文件并将 vue 预览添加到相应的列表中:

1
2
3
4
5
6
7
{
"presets": {
["env",{"modules": false}],
"stage-3",
"vue"
}
}

polyfill

添加 Babel polyfill,以便在旧浏览器中使用新的 JavaScript 特性。

在开发依赖中安装 babel-polyfill 包。

1
npm i -D babel-polyfill

在 src/main.js 文件的开头将其导入

import ‘babel-polyfill’

这将为浏览器启用所有必要的 polyfill。

4.2.5 更新依赖

1、手动更新

1
2
3
4
// 要检查项目中使用的包是否有新的版本,可以在根文件夹中运行以下命令:

npm outdated
npm install
不要忘记阅读你所更新包的更改日志!可能会有你希望了解的破坏性改变或改善。

2.自动更新

1
npm update
该命令只会更新与 package.json 文件中所指定版本兼容的版本。如果你想将包更新为其他版本,则需要手动执行。

3.更新 Vue

更新包含核心库的 Vue 包时,你也应该更新 vue-template-compiler 包。它是使用 webpack (或其他构件工具)时编译所有组件模板的包。

这两个包必须始终处于相同的版本。例如,如果你使用 vue 2.5.3 ,那么 vue-template-complier 也应该是版本 2.5.3.

4.2.6 为生产而构建

1
npm run build

默认情况下,使用 webpack-simple 模板时,它会将 JavaScript 文件输出到项目的 /dist 文件夹中。

4.3 单文件组件

Vue 具有自己的格式,名为单文件组件(SFC)。该格式由 Vue 团队创建,文件扩展名为 .vue。允许每个文件编写一个组件,将模板以及该组件的逻辑和样式集中在一个位置,这里的主要优势在于,每个组件都明显独立,更易于维护,易于共享。

单文件组件使用类似 HTML 的语法描述 Vue 组件。它可以包含 3 种类型的根块

1
2
3
<template>,使用我们已经用过的模板语法描述组件的模板;
<script>,其中包含组件的 JavaScript 代码;
<style>, 其中包含组件使用的样式。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<p>{{ message }}</p>
<input v-model="message" />>
</div>
</template>
<script>
export default {
data() {
return {
message: "Hello world"
};
}
};
</script>
<style>
p {
color: grey;
}
</style>

编辑 main.js 文件,并使用 import 关键字导入单文件组件;

1
import Test from './Test.vue'

移除 render 选项,使用对象展开运算符复制 Test 组件的定义:

1
2
3
4
new Vue({
el: '#app',
...Test
})
组件添加到应用程序的方法:使用 JavaScript 展开运算符,因此 ...App表达式将属性复制到应用定义对象。它的主要优点是,在开发工具中不再用无用的顶层组件;它会成为我们的根组件。

4.3.1 模板