Vue
介绍
响应的数据绑定和组合的视图组件
一套构建用户界面的 渐进式框架
Vue 采用自底向上增量开发的设计
Vue 的核心库只关注视图层
Vue 有能力驱动采用单文件组件和Vue生态系统支持的库开发的复杂单页应用
总览
1、Vue是以数据为驱动的,Vue自身将DOM和数据进行绑定,一旦创建绑定,DOM和数据将保持同步,每当数据发生变化,DOM会跟着变化。
2、ViewModel是Vue的核心,它是Vue的一个实例。Vue实例时作用域某个HTML元素上的,这个HTML元素可以是body,也可以是某个id所指代的元素。
3、DOM Listeners和Data Bindings是实现双向绑定的关键。DOM Listeners监听页面所有View层DOM元素的变化,当发生变化,Model层的数据随之变化;Data Bindings监听Model层的数据,当数据发生
变化,View层的DOM元素随之变化
Vue.js特点
简洁:页面由HTML模板+Json数据+Vue实例组成
数据驱动:自动计算属性和追踪依赖的模板表达式
组件化:用可复用、解耦的组件来构造页面 轻量:代码量小,不依赖其他库
快速:精确有效批量DOM更新
模板友好:可通过npm,bower等多种方式安装,很容易融入
选项:DOM
el
类型: string | HTMLElement
限制: 只在由 new 创建的实例中遵守。
详细:
为 Vue 实例提供 DOM 元素挂载。值可以是 CSS 选择符,或实际 HTML 元素。
在实例挂载之后, 元素可以用 vm.
e
l
访
问
。
如
果
这
个
选
项
在
实
例
化
时
有
作
用
,
实
例
将
立
即
进
入
编
译
过
程
,
否
则
,
需
要
显
式
调
用
v
m
.
el 访问。 如果这个选项在实例化时有作用,实例将立即进入编译过程,否则,需要显式调用 vm.
el访问。如果这个选项在实例化时有作用,实例将立即进入编译过程,否则,需要显式调用vm.mount() 手动开启编译。
template
类型: string
详细:
一个字符串模板作为 Vue 实例的标识使用。模板将会 替换 挂载的元素。挂载元素的内容都将被忽略,除非模板的内容有分发 slot。
如果值以 # 开始,则它用作选项符,将使用匹配元素的 innerHTML 作为模板。常用的技巧是用
render
类型: Function
详细:
字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。render 函数接收一个 createElement 方法作为第一个参数用来创建 VNode。
如果组件是一个函数组件,Render 函数还会接收一个额外的 context 参数,为没有实例的函数组件提供上下文信息。
选项:数据
data
类型: Object | Function
限制: 组件的定义只接受 function。
详细:
Vue 实例的数据对象。Vue 将会递归将 data 的属性转换为 getter/setter,从而让 data 的属性能够响应数据变化。对象必须是纯粹的对象(含有零个或多个的key/value对):浏览器 API 创建的原生对象,原型上的属性会被忽略。大概来说,data 应该只能是数据 - 不推荐观察拥有状态行为的对象。
一旦观察过,不需要再次在数据对象上添加响应式属性。因此推荐在创建实例之前,就声明所有的根级响应式属性。
实例创建之后,可以通过 vm.
d
a
t
a
访
问
原
始
数
据
对
象
。
V
u
e
实
例
也
代
理
了
d
a
t
a
对
象
上
所
有
的
属
性
,
因
此
访
问
v
m
.
a
等
价
于
访
问
v
m
.
data 访问原始数据对象。Vue 实例也代理了 data 对象上所有的属性,因此访问 vm.a 等价于访问 vm.
data访问原始数据对象。Vue实例也代理了data对象上所有的属性,因此访问vm.a等价于访问vm.data.a。
以 _ 或 $ 开头的属性 不会 被 Vue 实例代理,因为它们可能和 Vue 内置的属性、 API 方法冲突。你可以使用例如 vm.
d
a
t
a
.
p
r
o
p
e
r
t
y
的
方
式
访
问
这
些
属
性
。
当
一
个
组
件
被
定
义
,
d
a
t
a
必
须
声
明
为
返
回
一
个
初
始
数
据
对
象
的
函
数
,
因
为
组
件
可
能
被
用
来
创
建
多
个
实
例
。
如
果
d
a
t
a
仍
然
是
一
个
纯
粹
的
对
象
,
则
所
有
的
实
例
将
共
享
引
用
同
一
个
数
据
对
象
!
通
过
提
供
d
a
t
a
函
数
,
每
次
创
建
一
个
新
实
例
后
,
我
们
能
够
调
用
d
a
t
a
函
数
,
从
而
返
回
初
始
数
据
的
一
个
全
新
副
本
数
据
对
象
。
如
果
需
要
,
可
以
通
过
将
v
m
.
data._property 的方式访问这些属性。 当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。 如果需要,可以通过将 vm.
data.property的方式访问这些属性。当一个组件被定义,data必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果data仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供data函数,每次创建一个新实例后,我们能够调用data函数,从而返回初始数据的一个全新副本数据对象。如果需要,可以通过将vm.data 传入 JSON.parse(JSON.stringify(…)) 得到深拷贝的原始数据对象。
var data = { a: 1 }
// 直接创建一个实例
var vm = new Vue({
data: data
})
vm.a // -> 1
vm.$data === data // -> true
// Vue.extend() 中 data 必须是函数
var Component = Vue.extend({
data: function () {
return { a: 1 }
}
})
注意:不应该对 data 属性使用箭头函数 (例如data: () => { return { a: this.myProp }})。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.myProp 将是 undefined。
props
类型: Array | Object
详细:
props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义校验和设置默认值。
// 简单语法
Vue.component('props-demo-simple', {
props: ['size', 'myMessage']
})
// 对象语法,提供校验
Vue.component('props-demo-advanced', {
props: {
// 只检测类型
height: Number,
// 检测类型 + 其他验证
age: {
type: Number,
default: 0,
required: true,
validator: function (value) {
return value >= 0
}
}
}
})
propsData
类型: { [key: string]: any }
限制: 只用于 new 创建的实例中。
详细:
创建实例时传递 props。主要作用是方便测试。
var Comp = Vue.extend({
props: ['msg'],
template: '<div>{{ msg }}</div>'
})
var vm = new Comp({
propsData: {
msg: 'hello'
}
})
computed
类型: { [key: string]: Function | { get: Function, set: Function } }
详细:
计算属性将被混入到 Vue 实例中。所有 getter 和 setter 的 this 上下文自动地绑定为 Vue 实例。
注意:不应该使用箭头函数来定义计算属性函数 (例如 aDouble: () => this.a * 2)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。
计算属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。·
var vm = new Vue({
data: { a: 1 },
computed: {
// 仅读取,值只须为函数
aDouble: function () {
return this.a * 2
},
// 读取和设置
aPlus: {
get: function () {
return this.a + 1
},
set: function (v) {
this.a = v - 1
}
}
}
})
vm.aPlus // -> 2
vm.aPlus = 3
vm.a // -> 2
vm.aDouble // -> 4
methods
类型: { [key: string]: Function }
详细:
methods 将被混入到 Vue 实例中。可以直接通过 VM 实例访问这些方法,或者在指令表达式中使用。方法中的 this 自动绑定为 Vue 实例。
注意:不应该使用箭头函数来定义 method 函数 (例如 plus: () => this.a++)。理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.a 将是 undefined。
var vm = new Vue({
data: { a: 1 },
methods: {
plus: function () {
this.a++
}
}
})
vm.plus()
vm.a // 2
watch
类型: { [key: string]: string | Function | Object }
详细:
一个对象,键是需要观察的表达式,值是对应回调函数。值也可以是方法名,或者包含选项的对象。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。
var vm = new Vue({
data: {
a: 1,
b: 2,
c: 3
},
watch: {
a: function (val, oldVal) {
console.log('new: %s, old: %s', val, oldVal)
},
// 方法名
b: 'someMethod',
// 深度 watcher
c: {
handler: function (val, oldVal) { /* ... */ },
deep: true
}
}
})
vm.a = 2 // -> new: 2, old: 1
注意:不应该使用箭头函数来定义 watcher 函数
例如 searchQuery: newValue => this.updateAutocomplete(newValue)
,理由是箭头函数绑定了父级作用域的上下文,所以 this 将不会按照期望指向 Vue 实例,this.updateAutocomplete 将是 undefined。
声明式渲染
Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。
在底层的实现上, Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,在应用状态改变时, Vue 能够智能地计算出重新渲染组件的最小代价并应用到 DOM 操作上。
文本
数据绑定最常见的形式就是使用 “Mustache” 语法(双大括号)的文本插值:
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应数据对象上 msg 属性的值。无论何时,绑定的数据对象上 msg 属性发生了改变,插值处的内容都会更新。
通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新。但请留心这会影响到该节点上所有的数据绑定:
<span v-once>This will never change: {{ msg }}</span>
纯 HTML
双大括号会将数据解释为纯文本,而非 HTML 。为了输出真正的 HTML ,你需要使用 v-html 指令:
<div v-html="rawHtml"></div>
被插入的内容都会被当做 HTML —— 数据绑定会被忽略。注意,你不能使用 v-html 来复合局部模板,因为 Vue 不是基于字符串的模板引擎。组件更适合担任 UI 重用与复合的基本单元。
绑定 DOM 元素属性
Mustache 不能在 HTML 属性中使用,应使用 v-bind 指令:
<div v-bind:id="dynamicId"></div>
这对布尔值的属性也有效 —— 如果条件被求值为 false 的话该属性会被移除:
<button v-bind:disabled="someDynamicCondition">Button</button>
完整例子:
<div id="app-2">
<span v-bind:title="message">
Hover your mouse over me for a few seconds to see my dynamically bound title!
</span>
</div>
var app2 = new Vue({
el: '#app-2',
data: {
message: 'You loaded this page on ' + new Date()
}
})
使用 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 } }}
过滤器
Vue.js 允许自定义过滤器,被用作一些常见的文本格式化。
过滤器应该被添加在 mustache 插值的尾部,由“管道符”指示:
{{ message | capitalize }}
过滤器函数总接受表达式的值作为第一个参数。
new Vue({
// ...
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
过滤器可以串联:
{{ message | filterA | filterB }}
过滤器是 JavaScript 函数,因此可以接受参数:
{{ message | filterA('arg1', arg2) }}
这里,字符串 ‘arg1’ 将传给过滤器作为第二个参数, arg2 表达式的值将被求值然后传给过滤器作为第三个参数。
选项:生命周期钩子
vue生命周期
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、卸载等一系列过程,我们称这是Vue的生命周期。就是Vue实例从创建到销毁的过程,就是生命周期。
所有的生命周期钩子自动绑定 this 上下文到实例中,this直接指向的是vue的实例。因此可以访问数据,对属性和方法进行运算。这意味着不能使用箭头函数来定义一个生命周期方法 (例如 created: () => this.fetchTodos())。这是因为箭头函数绑定了父上下文,因此 this 与期待的 Vue 实例不同, this.fetchTodos 的行为未定义。
1、beforeCreate
类型: Function
详细:
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
2、created
类型: Function
详细:
实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
3、beforeMount
类型: Function
详细:在挂载开始之前被调用:相关的 render 函数首次被调用。
该钩子在服务器端渲染期间不被调用。
4、mounted
类型: Function
详细:
el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
该钩子在服务器端渲染期间不被调用。
5、beforeUpdate
类型: Function
详细:
数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
该钩子在服务器端渲染期间不被调用。
6、updated
类型: Function
详细:
由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态,因为这可能会导致更新无限循环。
该钩子在服务器端渲染期间不被调用。
7、activated
类型: Function
详细:
keep-alive 组件激活时调用。
该钩子在服务器端渲染期间不被调用。
8、deactivated
类型: Function
详细:
keep-alive 组件停用时调用。
该钩子在服务器端渲染期间不被调用。
9、beforeDestroy
类型: Function
详细:
实例销毁之前调用。在这一步,实例仍然完全可用。
该钩子在服务器端渲染期间不被调用。
10、destroyed
类型: Function
详细:
Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
该钩子在服务器端渲染期间不被调用。
Vue.js常用指令
指令(Directives)是带有 v- 前缀的特殊属性。指令属性的值预期是单一 JavaScript 表达式(除了 v-for,之后再讨论)。指令的职责就是当其表达式的值改变时相应地将某些行为应用到 DOM 上。
1、v-show指令: 条件渲染指令,一般用于频繁操作显示隐藏,与v-if不同的是,无论v-show的值为true或false,元素都会存在于HTML代码中。根据表达式之真假值,切换元素的 display CSS 属性。当条件变化时该指令触发过渡效果。
类型: any
2、v-if指令: 条件判断指令 ,只有当v-if的值为true,元素才会存在于 HTML代码中。根据表达式的值的真假条件渲染元素。在切换时元素及它的数据绑定 / 组件被销毁并重建。如果元素是 ,将提出它的内容作为条件块。当条件变化时该指令触发过渡效果。
类型: any
3、v-else指令: 可配合v-if使用,v-else指令必须紧邻v-if,否则该命令无法正常工 作。
v-else绑定的元素能否渲染在HTML中,取决于前面使用的是v-if。 若前面使用的是v-if,且v-if值为true,则v-else元素不会渲染
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
4、v-for指令: 循环指令,基于一个数组渲染一个列表,与JavaScript遍历类似
类型: Array | Object | number | string,基于源数据多次渲染元素或模板块。
必须使用特定语法 alias in expression ,为当前遍历的元素提供别名
v-for 指令可以绑定数据到数据来渲染一个列表:
<div id="app-4">
<ol>
<li v-for="todo in todos">
{{ todo.text }}
</li>
</ol>
</div>
var app4 = new Vue({
el: '#app-4',
data: {
todos: [
{ text: 'Learn JavaScript' },
{ text: 'Learn Vue' },
{ text: 'Build something awesome' }
]
}
})
另外也可以为数组索引指定别名(或者用于对象的键):
<div v-for="(item, index) in items"></div>
<div v-for="(val, key) in object"></div>
<div v-for="(val, key, index) in object"></div>
v-for 默认行为试着不改变整体,而是替换元素。迫使其重新排序的元素,您需要提供一个 key 的特殊属性:
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
5、v-bind指令: 给DOM绑定元素属性,动态地绑定一个或多个特性,或一个组件 prop 到表达式。
v-bind指令可以缩写为—> :
类型: any (with argument) | Object (without argument)
参数: attrOrProp (optional)
修饰符:.prop - 被用于绑定 DOM 属性。
在绑定 class 或 style 特性时,支持其它类型的值,如数组或对象。
在绑定 prop 时,prop 必须在子组件中声明。可以用修饰符指定不同的绑定类型。
没有参数时,可以绑定到一个包含键值对的对象。注意此时 class 和 style 绑定不支持数组和对象。
<!-- 绑定一个属性 -->
![在这里插入图片描述]()
<!-- 缩写 -->
![在这里插入图片描述]()
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]">
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 绑定一个有属性的对象 -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- 通过 prop 修饰符绑定 DOM 属性 -->
<div v-bind:text-content.prop="text"></div>
<!-- prop 绑定. “prop” 必须在 my-component 中声明。 -->
<my-component :prop="someThing"></my-component>
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
6、v-on指令: 用于监听DOM事件,绑定事件监听器。事件类型由参数指定。表达式可以是一个方法的名字或一个内联语句,如果没有修饰符也可以省略。
用在普通元素上时,只能监听 原生 DOM 事件。用在自定义元素组件上时,也可以监听子组件触发的自定义事件。
在监听原生 DOM 事件时,方法以事件为唯一的参数。如果使用内联语句,语句可以访问一个 $event 属性: v-on:click=“handle(‘ok’, $event)”。
v-on指令可以缩写为—>@
类型: Function | Inline Statement
参数: event (required)
修饰符:
.stop - 调用 event.stopPropagation()。
@click.stop 修饰符 阻止事件冒泡
@click.prevent 修饰符 阻止默认行为
.prevent - 调用 event.preventDefault()。
.capture - 添加事件侦听器时使用 capture 模式。
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.{keyCode | keyAlias} - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
.native - 监听组件根元素的原生事件。
<!-- 方法处理器 -->
<button v-on:click="doThis"></button>
<!-- 内联语句 -->
<button v-on:click="doThat('hello', $event)"></button>
<!-- 缩写 -->
<button @click="doThis"></button>
<!-- 停止冒泡 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认行为 -->
<button @click.prevent="doThis"></button>
<!-- 阻止默认行为,没有表达式 -->
<form @submit.prevent></form>
<!-- 串联修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 键修饰符,键别名 -->
<input @keyup.enter="onEnter">
<!-- 键修饰符,键代码 -->
<input @keyup.13="onEnter">
<!-- 在子组件上监听自定义事件(当子组件触发 “my-event” 时将调用事件处理器):-->
<my-component @my-event="handleThis"></my-component>
<!-- 内联语句 -->
<my-component @my-event="handleThis(123, $event)"></my-component>
<!-- 组件中的原生事件 -->
<my-component @click.native="onClick"></my-component>
7、v-html指令: 更新元素的 innerHTML 。
注意:内容按普通 HTML 插入,不会作为 Vue 模板进行编译 。如果试图使用 v-html 组合模板,可以重新考虑通过是否通过使用组件来替代,类型: string
<div v-html="html"></div>
8、v-text指令: 更新元素的 textContent。如果要更新部分的 textContent ,需要使用 {{ Mustache }} 插值,类型: string
<span v-text="msg"></span>
<!-- 和下面的一样 -->
<span>{{msg}}</span>
9、v-model指令: 在表单控件或者组件上创建双向绑定。
类型: 随表单控件类型不同而不同。
限制:、、、components
修饰符:
.lazy - 取代 input 监听 change 事件
.number - 输入字符串转为数字
.trim - 输入首尾空格过滤
计算属性
例子:
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
计算属性 vs method
<p>Reversed message: "{{ reverseMessage() }}"</p>
// in component
methods: {
reverseMessage: function () {
return this.message.split('').reverse().join('')
}
}
计算属性是基于它的依赖缓存。计算属性只有在它的相关依赖发生改变时才会重新取值。这就意味着只要 message 没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。
这也同样意味着如下计算属性将不会更新,因为 Date.now() 不是响应式依赖:
computed: {
now: function () {
return Date.now()
}
}
相比而言,每当重新渲染的时候,method 调用总会执行函数。
setter
计算属性默认只有 getter ,不过在需要时可以提供一个 setter :
// ...
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...
Class 与 Style 绑定
数据绑定一个常见需求是操作元素的 class 列表和它的内联样式。因为它们都是属性 ,可以用v-bind 处理它们:只需要计算出表达式最终的字符串。不过,字符串拼接麻烦又易错。因此,在 v-bind 用于 class 和 style 时, Vue.js 专门增强了它。表达式的结果类型除了字符串之外,还可以是对象或数组。
绑定 HTML Class
1、对象语法
我们可以传给 v-bind:class 一个对象,以动态地切换 class 。
<div v-bind:class="{ active: isActive }"></div>
上面的语法表示 classactive 的更新将取决于数据属性 isActive 是否为真值 。
也可以在对象中传入更多属性用来动态切换多个 class 。此外, v-bind:class 指令可以与普通的 class 属性共存。
如下模板:
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
如下 data:
data: {
isActive: true,
hasError: false
}
渲染为:
<div class="static active"></div>
当 isActive 或者 hasError 变化时,class 列表将相应地更新。
例如,如果 hasError 的值为 true , class列表将变为 “static active text-danger”。
也可以直接绑定数据里的一个对象:
<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
渲染的结果和上面一样。我们也可以在这里绑定返回对象的计算属性。这是一个常用且强大的模式:
<div v-bind:class="classObject"></div>
data: {
isActive: true,
error: null
},
computed: {
classObject: function () {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal',
}
}
}
2、数组语法
我们可以把一个数组传给 v-bind:class ,以应用一个 class 列表:
<div v-bind:class="[activeClass, errorClass]">
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
渲染为:
<div class="active text-danger"></div>
如果你也想根据条件切换列表中的 class ,可以用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]">
此例始终添加 errorClass ,但是只有在 isActive 是 true 时添加 activeClass 。
不过,当有多个条件 class 时这样写有些繁琐。可以在数组语法中使用对象语法:
<div v-bind:class="[{ active: isActive }, errorClass]">
3、用在组件上
当在一个定制的组件上用到 class 属性的时候,这些类将被添加到根元素上面,这个元素上已经存在的类不会被覆盖。
例如,如果你声明了这个组件:
Vue.component('my-component', {
template: '<p class="foo bar">Hi</p>'
})
然后在使用它的时候添加一些类:
<my-component class="baz boo"></my-component>
HTML 最终将被渲染成为:
<p class="foo bar baz boo">Hi</p>
同样的适用于绑定 HTML class :
<my-component v-bind:class="{ active: isActive }"></my-component>
当 isActive 为 true 的时候,HTML 将被渲染成为:
<div class="foo bar active"></div>
绑定内联样式
1、对象语法
v-bind:style 的对象语法十分直观——看着非常像 CSS ,其实它是一个 JavaScript 对象。 CSS 属性名可以用驼峰式(camelCase)或短横分隔命名(kebab-case):
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
直接绑定到一个样式对象通常更好,让模板更清晰:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
同样的,对象语法常常结合返回对象的计算属性使用。
2、数组语法
v-bind:style 的数组语法可以将多个样式对象应用到一个元素上:
<div v-bind:style="[baseStyles, overridingStyles]">
3、自动添加前缀
当 v-bind:style 使用需要特定前缀的 CSS 属性时,如 transform ,Vue.js 会自动侦测并添加相应的前缀。
双向数据绑定原理
Vue
使用 ES5 提供的访问器属性 Object.defineProperty() 方法,监控对数据的操作,Object.defineProperty方法第一个参数是要设置的对象,第二个参数是要对象的属性,第三个参数是一个对象,里面有set和get方法,当设置属性值或者获取属性值的时候就会执行这个set.get方法。
vue就是通过set方法,做到vue数据变更时,同时渲染页面数据。vue也会给dom对象绑定对象,这样页面数据变更时,也会对应的修改data。
AngularJS
采用“脏值检测”的方式,数据发生变更后,对于所有的数据和视图的绑定关系进行一次检测,识别是否有数据发生了改变,有变化进行处理,可能进一步引发其他数据的改变,所以这个过程可能会循环几次,一直到不再有数据变化发生后,将变更的数据发送到视图,更新页面展现。
如果是手动对 ViewModel 的数据进行变更,为确保变更同步到视图,需要手动触发一次“脏值检测”。
vuex 进行项目状态管理
计数器
state访问状态对象
mutations修改状态:传值 / 直接调用方法
getters计算过滤操作
Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理包含以下几个部分状态:
- state 驱动应用的数据源;
- view 以生命方式将 state 映射到视图。
- actions 响应在view 上的用户书输入导致的状态变化。
Vuex 规则
1、应用层级的状态应该集中到单个store 对象中。
2、提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
3、异步逻辑应该封装到action 里面。
具体介绍
路由
路由中有三个基本的概念 route, routes, router。
1, route,它是一条路由,由这个英文单词也可以看出来,它是单数, Home按钮 => home内容, 这是一条route, about按钮 => about 内容, 这是另一条路由。
2, routes 是一组路由,把上面的每一条路由组合起来,形成一个数组。[{home 按钮 =>home内容 }, { about按钮 => about 内容}]
3, router 是一个机制,相当于一个管理者,它来管理路由。因为routes 只是定义了一组路由,它放在哪里是静止的,当真正来了请求,怎么办? 就是当用户点击home 按钮的时候,怎么办?这时router 就起作用了,它到routes 中去查找,去找到对应的 home 内容,所以页面中就显示了 home 内容。
4,客户端中的路由,实际上就是dom 元素的显示和隐藏。当页面中显示home 内容的时候,about 中的内容全部隐藏,反之也是一样。客户端路由有两种实现方式:基于hash 和基于html5 history api.
vue-router 进行组件化开发
vue-router是Vue.js官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用。vue的单页面应用是基于路由和组件的,路由用于设定访问路径,并 将路径和组件映射起来,在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换
把路径和组件对应起来,然后在页面中把组件渲染出来
1、 页面实现(html模版中)
在vue-router中, 定义了两个标签<router-link> 和<router-view>来对应点击和显示部分。<router-link> 就是定义页面中点击的部分,<router-view> 定义显示部分,就是点击后,区配的内容显示在什么地方。所以 <router-link> 还有一个非常重要的属性 to,定义点击之后,要到哪里去, 如:<router-link to="/home">Home
2、 js 中配置路由
首先要定义route, 一条路由的实现。它是一个对象,由两个部分组成: path和component. path 指路径,component 指的是组件。如:{path:’/home’, component: home}我们这里有两条路由,组成一个routes:
const routes = [
{ path: '/home', component: Home },
{ path: '/about', component: About }
]
最后创建router 对路由进行管理,它是由构造函数 new vueRouter() 创建,接受routes 参数。
const router = new VueRouter({
routes // routes: routes 的简写
})
配置完成后,把router 实例注入到 vue 根实例中,就可以使用路由了
const app = new Vue({
router
}).$mount('#app')
执行过程:当用户点击 router-link 标签时,会去寻找它的 to 属性, 它的 to 属性和 js 中配置的路径{ path: ‘/home’, component: Home} path 一一对应,从而找到了匹配的组件, 最后把组件渲染到 标签所在的地方。所有的这些实现才是基于hash 实现的。
路由钩子函数
可以配置beforeEnter钩子
to:路由将要跳转的路径信息,信息是包含在对像里边的。
from:路径跳转前的路径信息,也是一个对象的形式。
next:路由的控制参数,next(true)和next(false)。
编程式导航
不用linkto改变地址,通过历史记录进行跳转
this.$router.go(-1) — 上一页
this.$router.go(1) — 后一页
this.$router.push(’/’) — 返回主页
动态路由
上面我们定义的路由,都是严格匹配的,只有router-link 中的to属性和 js 中一条路由route中 path 一模一样,才能显示相应的组件component。
但有时现实却不是这样的,当我们去访问网站并登录成功后,它会显示 欢迎你,+ 你的名字。不同的用户登录, 只是显示“你的名字” 部分不同,其它部分是一样的。这就表示,它是一个组件,假设是user组件。不同的用户(就是用户的id不同),它都会导航到同一个user 组件中。这样我们在配置路由的时候,就不能写死, 就是路由中的path属性,不能写死,那要怎么设置? 导航到 user 组件,路径中肯定有user, id 不同,那就给路径一个动态部分来匹配不同的id.
在vue-router中,动态部分以 : 开头,那么路径就变成了 /user/:id, 这条路由就可以这么写:
{ path:"/user/:id", component: user }.
vue-cli 搭建开发环境
vue-cli脚手架模板是基于node下的npm来完成安装的所以首先需要安装node
1、安装node
2、npm install --g vue-cli,安装完成之后输入 vue -V(注意-V大写),出现相应的版本号,则说明安装成功。
3、搭建项目:vue init
4、项目打包:npm run build
打包完成后,会在根目录下生成一个dist文件夹
5、运行项目:npm run dev
自动打开了浏览器,运行了vue项目