安装
兼容性
Vue
不支持IE8及以下版本。
引入
直接下载并用<script>
标签引入,Vue
会被注册为一个全局变量。
开发版本包含完整的警告和调试模式;生产版本删除了警告。
命令行工具(CLI)
//全局安装vue-cli
npm install --global vue-cli
//创建一个基于webpack模板的新项目
vue init webpack my-project
//安装依赖
cd my-project
npm install
npm run dev
对不同构建版本的解释
在NPM包的dist/
目录有很多不同的Vue.js
构建版本。
UMD | CommonJS | ES Module | |
---|---|---|---|
完整版 | vue.js | vue.common.js | vue.esm.js |
只包含运行时版 | vue.runtime.js | vue.runtime.common.js | vue.runtime.esm.js |
完整版(生产环境) | vue.min.js | - | - |
只包含运行时版(生产环境) | vue.runtime.min.js | - | - |
术语
完整版:同时包含编译器和运行时的版本。
编译器:用来将模板字符串编译成为JavaScript渲染函数的代码。
运行时:用来创建Vue
实例、渲染并处理虚拟DOM等的代码。基本上就是除去编译器的其它一切。
UMD:UMD版本可以通过<script>
标签直接用在浏览器中。
CommonJS:CommonJS版本用来配合老的打包工具比如Browserify或webpack1。这些打包工具的默认文件(pkg.main
)是只包含运行时的CommonJS版本。
ES Module:ES module版本用来配合现代打包工具比如webpack2。这些打包工具的默认文件(pkg.module
)是只包含运行时的ES Module版本。
运行时+编译器vs只包含运行时
如果需要在客户端编译模板 (比如传入一个字符串给template
选项,或挂载到一个元素上并以其DOM内部的HTML作为模板),就将需要加上编译器,即完整版。
// 需要编译器
new Vue({
template: '<div>{{ hi }}</div>'
})
// 不需要编译器
new Vue({
render (h) {
return h('div', this.hi)
}
})
当使用vue-loader
或vueify
的时候,*.vue
文件内部的模板会在构建时预编译成JavaScript。最终打好的包里实际上是不需要编译器的,所以只用运行时版本即可。
因为运行时版本相比完整版体积要小大约30%,所以应该尽可能使用这个版本。如果你仍然希望使用完整版,则需要在打包工具里配置一个别名。
//webpack
module.exports = {
// ...
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js'
}
}
}
//Browserify
{
// ...
"browser": {
"vue": "vue/dist/vue.common.js"
}
}
开发环境vs生产环境
对于UMD版本来说,开发环境/生产环境模式是硬编码好的:开发环境下用未压缩的代码,生产环境下使用压缩后的代码。
CommonJS和ES Module版本是用于打包工具的,因此没有压缩后的版本。需要我们自行将最终的包进行压缩。
CommonJS和ES Module版本同时保留原始的process.env.NODE_ENV
检测,以决定它们应该运行在什么模式下。我们应该使用适当的打包工具配置来替换这些环境变量以便控制Vue
所运行的模式。把process.env.NODE_ENV
替换为字符串字面量同时可以让UglifyJS之类的压缩工具完全丢掉仅供开发环境的代码块,以减少最终的文件尺寸。
//webpack4+
module.exports = {
mode: 'production'
}
//webpack3
var webpack = require('webpack')
module.exports = {
// ...
plugins: [
// ...
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
]
}
Vue实例
创建一个Vue实例
每个Vue
应用都是通过用Vue
函数创建一个新的Vue
实例开始的。
var vm = new Vue({
// 选项
})
当创建一个Vue
实例时,可以传入一个选项对象。
一个Vue
应用由一个通过new Vue
创建的根Vue
实例,以及可选的嵌套的、可复用的组件树组成。
所有的Vue
组件都是Vue
实例,并且接受相同的选项对象 (一些根实例特有的选项除外)。
数据与方法
当一个Vue
实例被创建时,它向Vue
的响应式系统中加入了其 data
对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生响应,即匹配更新为新的值。
var data = { a: 1 } // 我们的数据对象
var vm = new Vue({
data: data // 该对象被加入到一个Vue实例中
})
// 获得这个实例上的属性
// 返回源数据中对应的字段
vm.a == data.a // => true
// 设置属性也会影响到原始数据
vm.a = 2
data.a // => 2
// ……反之亦然
data.a = 3
vm.a // => 3
当这些数据改变时,视图会进行重渲染。值得注意的是只有当实例被创建时data
中存在的属性才是响应式的。也就是说如果你添加一个新的属性,比如:
vm.b = 'hi'
那么对b
的改动将不会触发任何视图的更新。如果你知道你会在晚些时候需要一个属性,但是一开始它为空或不存在,那么你仅需要设置一些初始值。
data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
}
这里唯一的例外是使用Object.freeze()
,这会阻止修改现有的属性,也意味着响应系统无法再追踪变化。
var obj = {
foo: 'bar'
}
Object.freeze(obj)
new Vue({
el: '#app',
data: obj
})
<div id="app">
<p>{{ foo }}</p>
<!-- 这里的 `foo` 不会更新! -->
<button v-on:click="foo = 'baz'">Change it</button>
</div>
除了数据属性,Vue
实例还暴露了一些有用的实例属性与方法。它们都有前缀$
,以便与用户定义的属性区分开来。
var data = { a: 1 }
var vm = new Vue({
el: '#example',
data: data
})
vm.$data === data // => true
vm.$el === document.getElementById('example') // => true
// $watch 是一个实例方法
vm.$watch('a', function (newValue, oldValue) {
// 这个回调将在 `vm.a` 改变后调用
})
实例生命周期钩子
每个Vue
实例在被创建时都要经过一系列的初始化过程——例如,需要设置数据监听、编译模板、将实例挂载到DOM并在数据变化时更新DOM等。同时在这个过程中也会运行一些叫做生命周期钩子的函数,这给了用户在不同阶段添加自己的代码的机会。
比如created
钩子可以用来在一个实例被创建之后执行代码。
new Vue({
data: {
a: 1
},
created: function () {
// this指向vm实例
console.log('a is:'+this.a)
}
})
// => "a is: 1"
也有一些其它的钩子,在实例生命周期的不同阶段被调用,如mounted
、updated
和destroyed
。生命周期钩子的this
上下文指向调用它的Vue
实例。
不要在选项属性或回调上使用箭头函数,比如 created:()=>console.log(this.a)
或vm.$watch('a',newValue=>this.myMethod())
。因为箭头函数是和父级上下文绑定在一起的,this
不会是如你所预期的Vue
实例,经常导致Uncaught TypeError: Cannot read property of undefined
或Uncaught TypeError: this.myMethod is not a function
之类的错误。
生命周期图示
模板语法
Vue.js
使用了基于HTML的模板语法,允许开发者声明式地将DOM绑定至底层Vue
实例的数据。
在底层的实现上,Vue
将模板编译成虚拟DOM渲染函数。结合响应系统,Vue
能够智能地计算出最少需要重新渲染多少组件,并把DOM操作次数减到最少。
你也可以不用模板,直接写渲染(render
)函数,使用可选的JSX语法。
插值
文本
数据绑定最常见的形式就是使用双大括号的文本插值。
<span>Message: {{ msg }}</span>
双大括号标签将会被替代为对应数据对象上msg
属性的值。无论何时,绑定的数据对象上msg
属性发生了改变,插值处的内容都会更新。
通过使用v-once
指令,也能执行一次性地插值,当数据改变时,插值处的内容不会更新。
<span v-once>这个将不会改变: {{ msg }}</span>
原始HTML
双大括号会将数据解释为普通文本,而非HTML代码。为了输出真正的HTML,需要使用v-html
指令。
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
动态渲染的任意HTML可能会非常危险,因为它很容易导致XSS攻击。请只对可信内容使用HTML插值,绝不要对用户提供的内容使用插值。
特性
双大括号语法不能作用在HTML特性上,遇到这种情况应该使用v-bind
指令。
<div v-bind:id="dynamicId"></div>
在布尔特性的情况下,它们的存在即暗示为true
,v-bind
工作起来略有不同。
<button v-bind:disabled="isButtonDisabled">Button</button>
如果isButtonDisabled
的值是 null
、undefined
或false
,则disabled
特性甚至不会被包含在渲染出来的<button>
元素中。
使用JavaScript表达式
对于所有的数据绑定,Vue.js
都提供了完全的JavaScript表达式支持。
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
这些表达式会在所属Vue
实例的数据作用域下作为JavaScript被解析。有个限制就是,每个绑定都只能包含单个表达式,所以下面的例子都不会生效。
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如Math
和Date
。你不应该在模板表达式中试图访问用户定义的全局变量。
指令
指令是带有v-
前缀的特殊特性。指令特性的值预期是单个JavaScript表达式(v-for
是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM。
<p v-if="seen">现在你看到我了</p>
这里,v-if
指令将根据表达式seen
的值的真假来插入/移除<p>
元素。
参数
一些指令能够接收一个“参数”,在指令名称之后以冒号表示。例如,v-bind
指令可以用于响应式地更新HTML特性。
<a v-bind:href="url">...</a>
在这里href
是参数,告知v-bind
指令将该元素的href
特性与表达式url
的值绑定。
v-on
指令,它用于监听DOM事件。
<a v-on:click="doSomething">...</a>
在这里参数是监听的事件名。
修饰符
修饰符是以半角句号.
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent
修饰符告诉v-on
指令对于触发的事件调用event.preventDefault()
。
<form v-on:submit.prevent="onSubmit">...</form>
缩写
v-
前缀作为一种视觉提示,用来识别模板中Vue
特定的特性。Vue.js
为v-bind
和v-on
这两个最常用的指令,提供了特定简写。
v-bind缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
v-on缩写
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>