VUE2.0官方文档
基础部分:
1.VUE简介
Vue是一个基于MVVM的框架,其中M代表数据处理层,V代表视图层即我们在Vue组件中的html部分,VM即M和V的结合层,处理M层相应的逻辑数据,在V层实现渲染。Vue让我们把精力更多的放在VM层上,即更多的关注业务逻辑,把DOM操作交给系统。
1)声明式渲染:在vue实例对象中进行数据声明,在V层响应式的进行DOM渲染。
2)条件与循环:v-if、v-for
3)处理用户输入:v-model
4)构建组件化应用:在大型应用中将应用程序划分为小型、独立和可复用的组件,使开发更易管理
vue自定义组件和Web组件规范中自定义元素的关系:
Vue组件语法部分参考了Web组件规范,有几个关键差别:
a)Web Components 规范未被所有浏览器原生实现,但是Vue组件被所有浏览器支持,且Vue组件可以包装于原生自定义元素之内。
b)Vue组件提供了纯自定义元素所不具备的一些重要功能,最突出的是跨组件数据流、自定义事件通信以及构建工具集成。
2.Vue实例
1)Vue实例创建:一个Vue应用由一个通过new Vue 创建的根Vue实例,以及可选的嵌套的、可复用的组件数组成。所有的Vue组件都是Vue实例,并且接受相同的选项对象(一些根实例特有的选项除外)。
2)Vue实例中允许在data对象中添加属性,且这些属性是响应式的。Vue还有一些有用的属性和方法,以$为前缀
3)实例生命周期钩子:
3.模板语法:
1)插值
a.文本插值:{}
b.解析HTML:v-html,会将数据解析为HTML代码渲染,但是不能使用v-html来复合局部模板。(站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS攻击。请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值)
c.绑定属性:v-bind
d.可以使用JS表达式:每个绑定只能包含单个表达式。(模板表达式都被放在沙盒中,只能访问全局变量的一个白名单,如 Math
和 Date
。你不应该在模板表达式中试图访问用户定义的全局变量)
2)指令
a)指令的职责:当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM
b)参数:一些指令能够接受一些参数,在指令名称之后用冒号表示(如:v-bind:href=“url”)
c)动态参数:从 2.6.0 开始,可以用方括号括起来的 JavaScript 表达式作为一个指令的参数
<a v-bind:[attributeName]="url"> ... </a>
(注:attributeName为null是可以用于显示的去除属性的绑定,且attributeName中不能包含引号、空格,大写会被转换成小写)
d)修饰符:以半角句号 .
指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。
例如,.prevent
修饰符告诉 v-on
指令对于触发的事件调用 event.preventDefault()
:
<form v-on:submit.prevent="onSubmit">...</form>
e)缩写:v-bind: =》 :
v-on:=> @
4.计算属性(computed)和侦听器(watch)
模板中表达式非常便利,但是它设计的初衷是用于简单运算,而不是处理复杂逻辑。在处理复杂逻辑是我们使用计算属性。
1)计算属性(computed):
计算属性和事件绑定的区别:计算属性存在缓存,只有当它的依赖发生变化时才会重新执行,但是事件绑定在每次访问都是会重新执行的。(这同时意味着如果计算属性中不存在依赖,那么计算属性的值将永远不变。)
getter:(默认只有getter),计算属性获取值
setter:根据计算属性反过来去改变其依赖的值
2)侦听器 watch:当需要在数据变化时执行异步或开销较大的操作时,使用侦听器更好。
5.Class与Style绑定
针对class列表和内联样式,v-bind做了专门的增强,值除了可以是字符串外,还可以是对象或者数组。
v-bind:class、v-bind:style : 通常有两种使用方式 -- 对象语法和数组语法
对象语法:
1)<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }" ></div>
data:{
isActive:true,
hasError:false
}
2)<div v-bind:class="classObject"></div>
data: {
classObject: {
active: true,
'text-danger': false
}
}
3)
同时可以使用计算属性改改变classObject值
<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' }
}
}
数组语法:
1)<div v-bind:class="[activeClass, errorClass]"></div>
data: {
activeClass: 'active',
errorClass: 'text-danger'
}
2)可以使用三元表达式:
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
3)在数组语法中也可以使用对象语法
<div v-bind:class="[{ active: isActive }, errorClass]"></div>
v-bind:style 使用需要添加浏览器前缀的css属性时,vue会自动添加。
从2.3.0 开始,v-bind:style 绑定的属性中可以提供一个包含多个值的数组,常用于提供多个带前缀的值,如:<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>,这样写只会渲染数组中最后一个被浏览器支持的值。
6.条件渲染
1)v-if
v-if-else(2.1.0新增)
v-else
用key 解决元素复用:vue会尽可能高效地渲染元素,通常会复用已有元素而不是从头渲染,这常常会造成元素不更新的情况,如果想避免这种问题,可以用key解决
2)v-show
v-show不同于v-if,v-show的元素始终会被渲染并保留在DOM中,它操作的是元素的display属性,同时v-show不支持<template>元素。
3)v-if 和 v-show 比较
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show
较好;如果在运行时条件很少改变,则使用 v-if
较好。
7.列表渲染
1)v-for
数组遍历:v-for = “(item,index)in items”
对象遍历:v-for ="(value,key,index)in object"
key:v-for情况下尽量使用绑定key属性
2)数组更新检测
a)变异方法(会改变数组的方法):push()、pop()、shift()、unshift()、splice()、sort()、reverse(),这些方法都会触发数组的更新
b)由于JavaScript的显示,vue不能检测一下变动的数组
- 当你利用索引直接设置一个项时,例如:
vm.items[indexOfItem] = newValue
- 当你修改数组的长度时,例如:
vm.items.length = newLength
- 当你利用索引直接设置一个项时,例如:
但是有解决方法:
vm.items[indexOfItem] = newValue 的解决方法 => 1) Vue.set(vm.items, indexOfItem, newValue)
2) Vm.items.splice(indexOfItem, 1, newValue)
vm.items.length = newLength 的解决方法 => vm.items.splice(newLength)
这些方法就会触发更新了
3)对象的更新检测
a) vue不能检测对象属性的添加和删除,对于已经创建的实例,vue不能动态添加跟级别的相应,但是可以使用 Vue.set(object, key, value)
方法向嵌套对象添加响应式属性。列如:
var vm = new Vue({
data: { userProfile: {
name: 'Anika'
}
}
})
Vue.set(vm.userProfile, 'age', 27)
b) 在为嵌套对象添加多个新属性时,应该这样做:
vm.userProfile = Object.assign({}, vm.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
4)一段取值范围的v-for
<div> <span v-for="n in 10">{{ n }} </span> </div> 结果:1 2 3 4 5 6 7 8 9 10
5)v-for 和 v -if 同时使用:v-for 的优先级高于 v-if
6)组件中使用v-for:数据不会自动传递到组件中,因为组件有自己的作用域,为了把迭代数据传到组件里,我们需要使用props
8.事件处理
1)监听事件 :v-on
2)事件处理:通常配合methods使用
3)事件修饰符:.stop .prevent .capture .self .once .passive
4)按键修饰符(按键码:尽量不适用按键码)
5)系统修饰键:.ctrl .alt .shift .meta .exact(精准修饰符)
6)鼠标修饰符: .left .right .middle
在HTML中设置事件监听的原因(这样能做是不是违背了我们希望把关注点放在VM层的原则,没有),因为vue都把这些(事件处理方法和表达式)绑定到了VM层了。同时使用v-on有如下好处:
-
扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。
-
因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。
-
当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们
9.表单输入绑定
1)基本用法:v-model,在相应元素上创建双向数据绑定,它会根据控件类型自动选取正确的方法来更新元素。
处理的元素包括:文本、多行文本、复选框(单个复选框绑定布尔值,多个复选框绑定到数组)、单选按钮、选择框(单选框和复选框)
2)修饰符:.lazy .number .trim
10.组件基础
1)组件是可复用的Vue实例,所以与new Vue 接受相同的选项(除了根实例特有的选项外)。
2)组件复用:组件是可以复用的,但是其中维护的数据,复用的组件都会有自己相应独立的数据,因为每用一次组件,就会有一个新实例被创建。(组件的data选项必须是一个函数,这样才能保障给每个实例都返回一个对象的独立拷贝)
3)通过Prop向子组件传递数据:通过在子组件上使用props选项为组件绑定相应的自定义属性,在调用子组件时设置相应属性的值就达到了向子组件传递数据的效果。
4)监听子组件事件:父组件可以通过子组件上的v-on监听子组件的任意事件,子组件首先通过$emit 触发自身绑定的事件,这时父组件就会接收到这个事件。
a.子组件可以通过$emit 来抛出一个值的
b.子组件上使用v-model:
对于正常的元素使用v-model:
但是在组件上使用v-model:
为了让其正常工作,组件内的<input>需要做相应的处理:
5)通过插槽分发内容(后面详述)
6)动态组件(后面详述)
7)在HTML中有些元素其内容元素内容或者其所属元素都是有规定的,如<table>中应该包含<tr>,但是如果在<table>中使用模板,会导致渲染出错。可以使用is 特性解决:
但是我们通过以下来源使用模板的话,就不会出现这样的问题了:
深入了解组件:
1.组件注册
1)组件名:组件名推荐使用短横线分割命名
2)全局注册:Vue.component(),全局注册的组件可以应用于其注册之后的任何新创建的Vue跟实例及其子组件中
3)局部注册:
局部注册的组件在子组件之间不可使用。
4)模块系统
a.在模块系统中局部注册:
b.基础组件的自动化全局注册(对于基础组件,我们应该自动化的全局部署他,而不是每个组件中局部部署)
全局导入基础组件的实例代码:
2.Prop
1)prop名如果使用驼峰命名法,在调用使用时需要使用短横线分割命名法。
2)Prop类型:通常使用对象的形式列出prop,指定值类型
3)传值:可以给prop设置的属性传入静态或动态的值,且可以传入任何类型的值
4)单向数据流:prop都是单向的,这样会防止从子组件意外改变父级组件的状态(对于对象和数组是通过引用传入的,会改变)
5)Prop验证:在设置props值时可以提供一个带有验证需求的对象,这样如果使用时一个类型不一致,Vue会在控制台中发出警告。(注意prop会在一个组件实例创建之前进行验证,所以实例的属性(如data、computed等)在default或validator函数中不可用)。
6)非Prop特性:在很多情况下我们并不知道一个组件将来会传入什么样的特性值,所以组件是可以接收任意特性的,而这些特性也会被添加到组件的根元素上。
a.对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内容原来设置好的值,但是对于class和style,值会合并。
b.在开发基础组件时,我们很多时候不需要其上层集成过来的元素特性,我们可以给组件设置 inheritAttrs :false 来禁用特性继承。(inheritAttrs:false 不会影响style 和 class 的绑定)
3.自定义事件
1)事件名:事件名是完全匹配的,所以不像组件名和prop名一样,camelCase的名字不会映射到kebab-case 名字上。同时v-on绑定的事件会自动转换为全小写。
因此,我们推荐所有命名使用kebab-case 命名
2)自定义组件使用v-model:v-model会默认利用名为value的prop和名为 input 的事件,但是对于像单选框这样的输入控件会对value有不同的目的,使用model选项可以用来避免这样的冲突。
3)将原生事件绑定到组件
4).sync 修饰符:默认情况下组件通信是单向的,如果我们希望子组件改变父组件,我们一般通过子组件传递事件来实现。
为了方便起见,Vue为这种方式提供了一种缩写,即.sync 修饰符
4.插槽
1)插槽的内容:带有插槽的组件在使用时可以向其中填充任何模板代码和HTML
2)插槽的作用域:父级模板里的内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。
3)后备内容:插槽在没有提供内容时默认显示的内容
4)具名插槽:插槽可以绑定一个name 属性,在使用时,<template v-solt:name 属性值> 即可用<temlate> 标签之间的内容替换掉插槽
5)作用域插槽:插槽只可以访问在定义时所在的vue实例中的数据,在模板中定义插槽时有时插槽会访问子组件中的数据,但在使用时,直接使用时是调用不了子组件中的数据的。这时候在插槽定义中使用插槽prop,在调用时<template> 上用v-slot 定义一个插槽prop的别名,利用别名就可以在使用时访问到相应数据。
解构插槽prop:插槽别名可以直接使用ES5解构,如{user}这样的形式。
插槽名可以使用动态的:v-slot:[dynamicSlotName]
v-slot缩写:#
5.动态组件&异步组件
1)动态组件保持原来的状态,不重新渲染:使用<keep-alive>
2)异步组件:??没看懂
6.处理边界情况(在某些情况下,我们需要对vue的规则做一些特殊调整,不过这些调整都是有优势和劣势的,如何取舍使用根据具体情况使用)
1)访问元素和组件(在大多数情况下我们最好不要手动操作一个组件实例内部或者DOM,但是在某些情况下是必要的)
a)访问根实例:$root (推荐使用Vuex来管理应用的状态)
b)访问父级组件实例:$parent ($parent 容易是应用造成混乱,在向任意深层次组件提供信息是推荐使用依赖注入)
c)访问子组件:在子组件定义时可以添加一个ref属性,后期可以通过$.refs.属性值来访问到这个子组件($refs 只在组件渲染完成之后生效,且并不是响应式的)
d)依赖注入:可以在父组件中使用provide属性定义响应的数据或方法,后代组件使用reject就可以接受的响应的数据或方法。(但是依赖注入会是程序变得耦合 ,且所提供的属性时非响应式的,所以还是推荐使用Vuex )
2)程序化的事件侦听器(不经常使用)
3)循环引用
组件之间可以循环引用,但要注意设置一个点 ,结束这种循环关系,防止死循环。