每一个Vue Application必须建立一个root Vue Instance。html
<script> var vm = new Vue({ }); </script>
一个Vue实例至关于一个MVVM模式中的ViewModel。在建立Vue实例时,能够传入一个选项对象,包含数据、模板、挂载元素、方法、生命周期钩子等选项。vue
Vue.js经过构造函数Vue{ option }建立一个Vue实例:node
var vm = new Vue({ option });
<div id="app"></div> <script> var vm = new Vue({ el: "#app" }); </script>
<div id="app">{{ title }}</div> <script> var vm = new Vue({ el: "#app", data: { title: "标题" } }); </script>
每一个Vue实例建立时,都会经历一些列的初始化过程,调用相应的生命周期钩子。npm
Vue生命周期钩子:数组
◊ created:实例建立完成后调用,此阶段完成数据监测等,但还没有挂载,$el 还不可用。缓存
◊ mounted:el 挂载到实例后调用。app
<div id="app">{{ title }}</div> <script> var vm = new Vue({ el: "#app", data: { title: "标题" }, created: function () { console.log("Vue instance has been created!"); } }); </script>
<div id="app">{{ title }}</div> <script> var vm = new Vue({ el: "#app", data: { title: "标题" }, created() { console.log("Vue instance has been created!"); }, mounted() { console.log("mounted:" + this.$el); // <div id="app"></div> // console.log("mounted:" + this.$el.id); } }); </script>
Vue.js建立实例对象的选项中影响模板或DOM的选项:el 和 template。函数
◊ el :类型为字符串,DOM 元素或函数。其做用是为实例提供挂载元素。性能
◊ template:类型为字符串。默认会将template 值替换挂载元素(即el 值对应的元素),并合并挂载元素和模板根节点的属性。this
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>libing.vue</title> <script src="node_modules/vue/dist/vue.min.js"></script> </head> <body> <div id="app"> <h1>将被模板内容替换</h1> </div> <template id="tpl"> <div class="tpl">Todo List</div> </template> <script> var vm = new Vue({ el: "#app", template: "#tpl" }); </script> </body> </html>
渲染输出HTML:
<body> <div class="tpl">Todo List</div> <template id="tpl"> <div class="tpl">Todo List</div> </template> <script> var vm = new Vue({ el: "#app", template: "#tpl" }); </script> </body>
Vue.js使用基于HTML的模版语法,容许声明式地将DOM绑定至Vue实例的数据。
Vue.js的核心:采用模板语法声明式的将数据渲染到DOM。
Vue.js 实例中经过 data 属性定义数据,这些数据能够在实例对应的模板中进行绑定并使用。
数据绑定:{{ }}
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>libing.vue</title> <script src="node_modules/vue/dist/vue.min.js"></script> </head> <body> <div id="app"> <h1>{{ title }}</h1> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" } }); </script> </body> </html>
{{ }}:将数据中的 HTML 转为纯文本后再进行插值。
v-html :输出 HTML 代码
<div id="app"> <div v-html="title"></div> </div> <script> var vm = new Vue({ el: "#app", data: { title: "<h1>Todo List</h1>" } }); </script>
不能在 Vue 模板中的 HTML 属性上使用{{}}语法。
HTML 属性中的值应使用 v-bind 指令。
<div id="app"> <div v-bind:title="title">Content</div> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" } }); </script>
<div id="app"> {{ status ? "是" : "否" }} <div v-bind:title="status?'是':'否'">Content</div> </div> <script> var vm = new Vue({ el: "#app", data: { status: true } }); </script>
Vue.js 容许在表达式后添加可选的过滤器,以管道符 “|” 指示。
<div id="app"> <h1>{{ title | uppercase }}</h1> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" }, filters: { uppercase: function (value) { return value.toUpperCase(); } } }); </script>
多个过滤器链式使用:
{{ name | filterA | filterB }}
传入多个参数:
{{ name | filterA arg1 arg2}}
此时,filterA 将 name 的值作为第一个参数,arg1,arg2 作为第2、第三个参数传入过滤器函数中。
Vue.js 提供全局方法Vue.filter() 注册一个自定义过滤器,接受过滤器ID 和过滤器函数两个参数。
过滤器注册语法格式:
Vue.filter( id, [definition] )
示例:日期格式过滤器
引入moment.js:
npm install -S moment
import Vue from 'vue' import moment from 'moment' Vue.filter('datefmt', function (input, fmtstring) { return moment(input).format(fmtstring); }); new Vue({ el: '#app', data: { now: new Date() } })
{{ now | datefmt('YYYY-MM-DD HH:mm:ss') }}
指令是带有 v- 前缀的特殊属性。
指令用于在表达式的值改变时,将某些行为应用到 DOM 上。
v-bind指令:用于响应式地更新 HTML 属性。
v-on 指令:用于监听 DOM 事件。
<div id="app"> <h1 v-if="status">{{ title }}</h1> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List", status: true } }); </script>
一些指令可以接受一个参数,参数在指令后以冒号(:)表示。
<div id="app"> <a v-bind:href="url">libingql</a> </div> <script> var vm = new Vue({ el: "#app", data: { url: "https://www.cnblogs.com/libingql" } }); </script>
修饰符:以句号 . 表示的特殊后缀,用于指出一个指定应该以特殊方式绑定。
示例:.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()
<form v-on:submit.prevent="onSubmit"></form>
在 input 输入框中使用 v-model 指令来实现双向数据绑定。
<div id="app"> <div>{{ title }}</div> <input type="text" v-model="title" /> </div> <script> var vm = new Vue({ el: "#app", data: { title: "Todo List" } }); </script>
Vue.js 为 v-bind
和 v-on
这两个最经常使用的指令,提供特定简写。
<!-- 完整语法 --> <a v-bind:href="url"> ... </a> <!-- 简写 --> <a :href="url"> ... </a>
<!-- 完整语法 --> <a v-on:click="doSomething"> ... </a> <!-- 简写 --> <a @click="doSomething"> ... </a>
v-if指令:条件判断
在 <template> 上使用 v-if 进行条件分组
<div id="app"> <h1 v-if="seen">Todo List</h1> <template v-if="ok"> <ul> <li>Todo Item</li> <li>Todo Item</li> <li>Todo Item</li> </ul> </template> </div> <script> var vm = new Vue({ el: "#app", data: { seen: true, ok: true } }); </script>
v-if / v-else语句块:
<div id="app"> <h1 v-if="ok">是</h1> <h1 v-else>否</h1> </div> <script> var vm = new Vue({ el: "#app", data: { ok: true } }); </script>
v-if-else:v-if 以后的“else-if 块”,能够屡次链式地调用。
<div id="app"> <div v-if="type === 'A'"> A </div> <div v-else-if="type === 'B'"> B </div> <div v-else-if="type === 'C'"> C </div> <div v-else> Not A/B/C </div> </div> <script> new Vue({ el: '#app', data: { type: 'C' } }); </script>
v-show:根据条件展现元素
v-show 的元素会始终渲染并保留在 DOM 中。v-show 只会切换元素的 display 这个 CSS 属性。
<div id="app"> <h1 v-show="ok">Todo List</h1> </div> <script> var vm = new Vue({ el: "#app", data: { ok: true } }); </script>
注:v-show
没法用于 <template>
元素,也不能和 v-else
配合使用。
v-if 是“真实”的条件渲染,由于它会确保条件块(conditional block)在切换的过程当中,完整地销毁(destroy)和从新建立(re-create)条件块内的事件监听器和子组件。
v-if 是惰性的(lazy):若是在初始渲染时条件为 false,它不会执行任何操做 - 在条件第一次变为 true 时,才开始渲染条件块。
v-show 无论初始条件如何,元素始终渲染,而且只是基于 CSS 的切换。
一般来讲,v-if 在切换时有更高的性能开销,而 v-show 在初始渲染时有更高的性能开销。
若是须要频繁切换,推荐使用 v-show,若是条件在运行时改变的可能性较少,推荐使用 v-if。
v-for 遍历数组格式: item in items
其中,
items 是原始数据数组(source data array),
item 是数组中每一个迭代元素的指代别名(alias)。
<div id="app"> <ul> <li v-for="item in items">{{ item.text }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { items: [{ id: 1, text: "Vue" }, { id: 2, text: "Angular" }, { id: 3, text: "React" }] } }); </script>
<div id="app"> <ul> <li v-for="item in list">{{ item.text }}</li> </ul> </div> new Vue({ el: '#app', data: { list: [{ id: 1, text: 'Vue' }, { id: 2, text: 'Angular' }, { id: 3, text: 'React' }] } });
v-for索引参数:
<li v-for="(item, index) in items">{{ index }}-{{ item.text }}</li>
其中,index从0开始。
v-for
能够遍历对象的属性。
<div id="app"> <ul> <li v-for="value in item">{{ value }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { item: { id: 1, text: "Vue" } } }); </script>
v-for遍历对象属性:两个参数key、value
<div id="app"> <ul> <li v-for="(value, key) in item">{{ key }}:{{ value }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { item: { id: 1, text: "Vue" } } }); </script>
v-for遍历对象属性:3个参数index、key、value,索引(index)从0开始。
<div id="app"> <ul> <li v-for="(value, key, index) in item">{{ index }}-{{ key }}:{{ value }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { item: { id: 1, text: "Vue" } } }); </script>
为便于 Vue 跟踪每一个节点的身份,从新复用(reuse)和从新排序(reorder)现有元素,须要为每项提供惟一的 key 属性,从而给 Vue 一个提示。
理想的 key 值是每项都有惟一的 id。
推荐:在使用 v-for 时,尽量提供一个 key,除非迭代的 DOM 内容足够简单,或者是故意依赖于默认行为来得到性能提高。
<div id="app"> <ul> <li v-for="item in items" v-bind:key="item.id">{{ item.text }}</li> </ul> </div> <script> var vm = new Vue({ el: "#app", data: { items: [{ id: 1, text: "Vue" }, { id: 2, text: "Angular" }, { id: 3, text: "React" }] } }); </script>
简写:
<li v-for="item in items" :key="item.id">{{ item.text }}</li>
v-for能够在整数值范围内迭代。
<div id="app"> <ul> <li v-for="n in 10">{{ n }}</li> </ul> </div> <script> new Vue({ el: '#app' }); </script>
在模板中使用表达式是很是方便直接的,只适用于简单的操做,不适于加入过多的逻辑。
对于复杂的逻辑,使用 computed 属性(computed property)。
计算属性都以函数的形式,在Vue实例的computed选项中,最终返回计算后的结果。
<div id="app"> {{ fullName }} </div> <script> new Vue({ el: '#app', data: { firstName: "bing", lastName: "li" }, computed: { fullName: function () { return this.lastName + ' ' + this.firstName; } } }); </script>
计算属性依赖一个或多个Vue实例的数据,只要其中任一数据变化,计算属性就会从新执行,视图(vm)也会更新。
<div id="app"> <table> <tr> <th>商品ID</th> <th>商品名称</th> <th>单价</th> <th>数量</th> </tr> <tr v-for="item in products"> <td>{{ item.ID }}</td> <td>{{ item.ProductName }}</td> <td>{{ item.UnitPrice }}</td> <td> <input type="text" v-model="item.Quantity" /> </td> </tr> <tr> <td colspan="4" style="text-align: right;">总计:{{ total }}</td> </tr> </table> </div> <script> var vm = new Vue({ el: "#app", data: { products: [{ ID: 1, ProductName: "手机", UnitPrice: 1000, Quantity: 2 }, { ID: 2, ProductName: "电脑", UnitPrice: 5000, Quantity: 5 }] }, computed: { total: function () { var total = 0; for (var i = 0; i < this.products.length; i++) { total += this.products[i].Quantity * this.products[i].UnitPrice; } return total; } } }); </script>
computed 属性默认只有 getter ,能够在须要时提供一个 setter 。
<div id="app"> {{ fullName }} </div> <script> var vm = new Vue({ el: '#app', data: { firstName: "Bing", lastName: "Li" }, computed: { fullName: { get: function () { return this.lastName + ' ' + this.firstName; }, set: function (value) { var names = value.split(' ') this.lastName = names[0] this.firstName = names[names.length - 1] } } } }); vm.fullName = "Li Bing2018"; </script>
computed属性会基于它所依赖的数据进行缓存。每一个 computed 属性,只有在它所依赖的数据发生变化时,才会从新取值(re-evaluate)。
<div id="app"> {{ now }} </div> <script> new Vue({ el: '#app', computed: { now: function () { return Date.now() } } }); </script>
method方法:每当触发从新渲染(re-render)时,method 调用方式将老是再次执行函数。
在某些场景下,不但愿有缓存,使用 method 方法替代。
<div id="app"> {{ now() }} </div> <script> new Vue({ el: '#app', methods: { now: function () { return Date.now() } } }); </script>
watch 属性:Vue 提供的一种更加通用的方式,来观察和响应 Vue 实例上的数据变化。
过分滥用 watch 属性会形成一些问题,更推荐的方式是,使用 computed 属性。
<div id="app"> <input type="text" v-model="firstName"> <input type="text" v-model="lastName"> <div>{{ fullName }}</div> </div> <script> new Vue({ el: '#app', data: { firstName: 'Bing', lastName: 'Li', fullName: 'Li Bing' }, computed: { firstName: function (val) { this.fullName = this.lastName + ' ' + val; }, lastName: function (val) { this.fullName = val + ' ' + this.firstName; } } }); </script>
<script> new Vue({ el: '#app', data: { firstName: 'Bing', lastName: 'Li', fullName: 'Li Bing' }, watch: { firstName: function () { this.fullName = this.lastName + ' ' + this.firstName; }, lastName: function () { this.fullName = this.lastName + ' ' + this.firstName; } } }); </script>
向 v-bind:class
传入一个对象,来动态地切换 class。
<div id="app"> <div v-bind:class="{ active: isActive }"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true } }); </script>
渲染:
<div class="active"></div>
active 这个 class 的存在与否,取决于 isActive 这个 data 属性的 truthy 值。
v-bind:class 指令能够和普通 class 属性共存。能够经过在对象中添加多个字段,来切换多个 class。
<div id="app"> <div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: false } }); </script>
渲染:
<div class="static active"></div>
绑定对象,能够无需内联。
<div id="app"> <div v-bind:class="className"></div> </div> <script> new Vue({ el: '#app', data: { className: { active: true, 'text-danger': true } } }); </script>
渲染:
<div class="active text-danger"></div>
绑定返回对象的计算属性。
<div id="app"> <div v-bind:class="className"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true, hasError: true }, computed: { className: function () { return { active: this.isActive, 'text-danger': this.hasError } } } }); </script>
能够向 v-bind:class 传入一个数组,来与 class 列表对应。
<div id="app"> <div v-bind:class="[activeClass, errorClass]"></div> </div> <script> new Vue({ el: '#app', data: { activeClass: 'active', errorClass: 'text-danger' } }); </script>
三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
数组语法中使用对象语法:
<div id="app"> <div v-bind:class="[{ active: isActive }, errorClass]"></div> </div> <script> new Vue({ el: '#app', data: { isActive: true, errorClass: 'text-danger' } }); </script>
v-bind:style 直接设置样式
<div id="app"> <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div> </div> <script> new Vue({ el: '#app', data: { activeColor: 'red', fontSize: 30 } }); </script>
渲染:
<div style="color: red; font-size: 30px;"></div>
绑定对象
<div id="app"> <div v-bind:style="style"></div> </div> <script> new Vue({ el: '#app', data: { style: { color: 'red', fontSize: '13px' } } }); </script>
v-bind:style 的对象语法,能够和 computed 属性结合使用,此 computed 属性所对应的 getter 函数须要返回一个对象。
v-bind:style 的数组语法,能够在同一个元素上,使用多个 style 对象。
<div id="app"> <div v-bind:style="[baseStyles, overridingStyles]"></div> </div> <script> new Vue({ el: '#app', data: { baseStyles: { color: 'red', fontSize: '30px' }, overridingStyles: { 'font-weight': 'bold' } } }); </script>
渲染:
<div style="color: red; font-size: 30px; font-weight: bold;"></div>
v-on 指令:监听 DOM 事件,并在事件被触发时执行 JavaScript 代码。
<div id="app"> <button v-on:click="counter += 1">增长 1</button> <div>按钮点击次数:{{ counter }}次</div> </div> <script> new Vue({ el: '#app', data: { counter: 0 } }); </script>
用于处理逻辑复琐事件
<div id="app"> <button v-on:click="greet">greet</button> </div> <script> var vm = new Vue({ el: '#app', data: { name: "Li Bing" }, methods: { greet: function (event) { // `this` 在方法里指当前 Vue 实例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }); // 能够用 JavaScript 直接调用方法 vm.greet() // -> 'Hello Li Bing!' </script>
<div id="app"> <button v-on:click="greet('Li Bing')">greet</button> </div> <script> var vm = new Vue({ el: '#app', methods: { greet: function (name) { alert('Hello ' + name + '!'); } } }); </script>
在事件处理程序中常见调用 event.preventDefault() 或 event.stopPropagation()
v-on 提供事件修饰符,以点(.)开头的指令后缀来表示。
◊ .stop
◊ .prevent
◊ .capture
◊ .self
◊ .once
<!-- 中止点击事件冒泡 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件再也不从新载入页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符能够链式调用 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时,使用事件捕获模式 --> <!-- 内部元素触发的事件先在此到处理,而后才交给内部元素进行处理 --> <div v-on:click.capture="doThis">...</div> <!-- 只有在 event.target 是元素自身时,才触发处理函数。 --> <!-- 也就是说,event.target 是子元素时,不触发处理函数 --> <div v-on:click.self="doThat">...</div>
v-on:click.prevent.self 阻止全部点击
v-on:click.self.prevent 只阻止元素自身的点击