配置
- Vue.config.productionTip = false:阻止 vue 在启动时生成生产提示。
创建一个vue实例
1 | new Vue({ |
模板语法
- 插值语法
- 功能:用于解析标签体内容
- 写法:,xxx是js表达式,且可以直接读取到data中的所有属性
- 指令语法
- 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件…..)
- 示例:v-bind:href=”xxx” 或 简写为 :href=”xxx”
数据绑定
- 单向绑定(v-bind):数据只能从data流向页面
- 双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data
- 注:
- 双向绑定一般都应用在表单类元素上
- v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
el与data的两种写法
- el有2种写法
- 1.new Vue时候配置el属性
- 2.先创建Vue实例,随后再通过vm.$mount(‘#root’)指定el的值
- 把new Vue创建的实例赋值给变量vm,然后使用vm.$mount(‘#root’)来添加
- data有2种写法
- 对象式: data: {}
- 函数式(组件只能用函数式): data() { return{}}
- 重点:由Vue管理的函数,一定不要写箭头函数=>,一旦写了,this就不再是Vue实例了
MVVM模型
- M:模型(Model):data中的数据
- V:视图(View):模板代码
- VM:视图模型(ViewModel):Vue实例
- 观察可发现:
- data中所有的属性,最后都出现在了vm身上。
- vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用
数据代理
- 定义:通过一个对象代理对另一个对象中属性的操作(读/写)
Object.defineproperty方法
- 定义:会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20let number = 18
let person = {
name:'张三',
sex:'男',
}
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
// 以上属性都可以在控制台被修改,删除delete person.age
// 当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
return number
},
// 当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
number = value
}
})
Vue中的数据代理
- 通过vm对象来代理data对象中属性的操作(读/写)
- 优点:更加方便的操作data中的数据
- 基本原理:
- 通过Object.defineProperty()把data对象中所有属性添加到vm上
- 为每一个添加到vm上的属性,都指定一个getter/setter
- 在getter/setter内部去操作(读/写)data中对应的属性
- 比如data对象中定义的属性,在vm中要使用_data.属性名来读取
事件处理
基本使用
- 使用
v-on:xxx 或 @xxx
绑定事件,其中xxx是事件名 - 事件的回调需要配置在methods对象中,最终会在vm上
- methods中配置的函数,不要用箭头函数!否则this就不是vm了
- methods中配置的函数,都是被Vue所管理的函数,
this的指向是vm 或 组件实例对象
- @click=”demo” 和 @click=”demo($event)” 效果一致,但后者可以传参
事件修饰符
prevent
:阻止默认事件stop
:阻止事件冒泡once
:事件只触发一次capture
:使用事件的捕获模式,先捕获在冒泡self
:只有event.target是当前操作的元素时才触发事件,self也能阻止冒泡passive
:事件的默认行为立即执行,无需等待事件回调执行完毕- @scroll滚动条滚动触发,到滚动条末端不会再触发,
- 流程:优先滚动滚动条,然后在执行事件,不需要passive
- @wheel鼠标的滚轮滚动触发,到滚动条末端,只要滚轮在动就会触发
- 流程:滚动滚轮,先执行事件,后滚动条在往下走,passive后:先滚动,在执行demo
- @scroll滚动条滚动触发,到滚动条末端不会再触发,
- 示例:
<div @click.prevent.stop="showInfo">修饰符可以连续使用</div>
键盘事件
@keydown
:键盘按下时触发@keyup
:键盘弹起@keypress
:键盘按住时触发常用的按键别名
- 回车 => @keyup.enter
- 删除 => @keyup.delete (捕获“删除”和“退格”键)
- 退出 => @keyup.esc
- 空格 => @keyup.space
- 换行 => @keyup.tab (特殊,必须配合keydown去使用) 把当前元素当前位置切走
- 上 => @keyup.up
- 下 => @keyup.down
- 左 => @keyup.left
- 右 => @keyup.right
- Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要转为kebab-case形式
系统修饰键(用法特殊):ctrl、alt、shift、meta(windows键)
- 配合keyup使用:按下修饰键的同时,再按下任意键,随后释放任意键,事件才被触发
- 比如按ctrl+y,还可以用ctrl.y来指定只有使用ctrl+y才可以触发事件
- 配合keydown使用:正常触发事件。
- 配合keyup使用:按下修饰键的同时,再按下任意键,随后释放任意键,事件才被触发
鼠标按键修饰符
- .left
- .right
- .middle
- Vue.config.keyCodes.自定义键名 = 键码,可以去定制按键别名
- 更多别名
计算属性(computed)
- 定义:要用的属性不存在,要通过已有属性计算得来。
- 原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
- get函数什么时候执行?
- 初次读取时会执行一次。
- 当依赖的数据发生改变时会被再次调用。
- 优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
- 备注:
- 计算属性最终会出现在vm上,直接读取使用即可。
- 如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17computed:{
// 简写(只读不写)
fullName(){
return this.firstName + '-' + this.lastName
}
//完整写法
fullName: {
get() {
return this.firstName + '-' + this.lastName
},
set(value){
const arr = value.split('-')
this.firstName= arr[0]
this.lastName = arr[1]
}
}
}
监视属性(watch)
- 当被监视的属性变化时, 回调函数自动调用, 进行相关操作
- 监视的属性必须存在,才能进行监视
- 写法
- new Vue时传入watch配置
- 通过vm.$watch监视
- 深度监视
- deep:true可以监视多级结构中所有属性的变化
1 | watch:{ |
computed和watch之间的区别
- computed能完成的功能,watch都可以完成。
- watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。
- 两个重要的原则
- 所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm 或 组件实例对象。
- 所有不被Vue所管理的函数(定时器的回调函数、ajax的回调函数等、Promise的回调函数),最好写成箭头函数,这样this的指向才是vm 或 组件实例对象。
绑定样式
class样式
- 写法:class=”xxx” xxx可以是字符串、对象、数组。
- 字符串写法适用于:类名不确定,要动态获取。
- 对象写法适用于:要绑定多个样式,个数不确定,名字也不确定。
- 数组写法适用于:要绑定多个样式,个数确定,名字也确定,但不确定用不用。
- 写法:class=”xxx” xxx可以是字符串、对象、数组。
style样式
:style="{fontSize: xxx}"
:其中xxx是动态值。:style="[a,b]"
:其中a、b是样式对象。
条件渲染
v-if
- 语法:
- v-if=”表达式”
- v-else-if=”表达式”
- v-else=”表达式”
- 适用于:切换频率较低的场景。
- 特点:不展示的DOM元素直接被移除。
- 注意:v-if可以和v-else-if、v-else一起使用,但要求结构不能被”打断”
- 语法:
v-show
- 语法:v-show=”表达式”
- 适用于:切换频率较高的场景。
- 特点:不展示的DOM元素未被移除,仅仅是使用样式隐藏掉
- 备注:
- template只能与v-if一起用
- 使用v-if的时,元素可能无法获取到,而使用v-show一定可以获取到。
列表渲染
基本列表(v-for指令):
- 用于展示列表数据
- 语法:
v-for="(item, index) in/of xxx" :key="index"
- 可遍历:数组、对象、字符串(不常用)、指定次数(不常用,of 次数)
v-for 与 对象
- value:表值
- key:表属性名
- index:表索引
- 语法:
<li v-for="(value, key) in myObject">{{value}}</li>
在 v-for 里使用范围值
- 语法:
<span v-for="n in 10">{{ n }}</span>
<template> 上的 v-for
- 语法:
<template v-for="item in items"></template>
v-for 与 v-if
- 在同一节点,v-if 比 v-for 的优先级更高!!
在组件标签上使用
1 | <MyComponent |
列表过滤
- 表单使用v-model实现双向数据绑定
- 在计算属性或者监听属性上处理数据,并使用filter
- 字符串的模糊搜索,使用indexof
- 示例:
1
2
3
4
5
6
7computed:{
handler() {
return list.filter((item) => {
return item.str.indexof(keyWord) !== -1
})
}
}
列表排序
- 使用arr.sort((p1,p2)=>{})来判断
- p2-p1是降序(高到低),p1-p2是升序(从低到高)
数组变化侦测
push()
:将一个或多个元素添加到数组的末尾,并返回该数组的新长度pop()
:从数组中删除最后一个元素,并返回该元素的值shift()
:从数组中删除第一个元素,并返回该元素的值unshift()
:将一个或多个元素添加到数组的开头,并返回该数组的新长度splice()
:删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。sort()
:排序(升序)。此方法会改变原数组。reverse()
:排序(降序)。此方法会改变原数组。- 替换原数组:
items.value = items.value.filter(item => 条件)
filter()
:过滤
react、vue中的key有什么作用?(key的内部原理)
- 虚拟DOM中key的作用:
- key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据新数据生成新的虚拟DOM>, 随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较
- 对比规则:
- 旧虚拟DOM中存在与新虚拟DOM相同的key
- 内容没变, 使用旧的真实DOM
- 内容变了, 则生成新的真实DOM,并替换掉旧的真实DOM
- 旧虚拟DOM中未找到与新虚拟DOM相同的key
- 创建新的真实DOM,随后渲染到到页面
- 旧虚拟DOM中存在与新虚拟DOM相同的key
- 用index作为key可能会引发的问题:
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
- 会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
- 如果结构中还包含输入类的DOM:
- 会产生错误DOM更新 ==> 界面有问题
- 若对数据进行:逆序添加、逆序删除等破坏顺序操作:
- 开发中如何选择key?
- 最好使用每条数据的唯一标识作为key
- 如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
Vue检测数据改变的原理
vue.set()
- 使用场景:对数组或对象进行操作时,有些操作是非响应式的,所以使用Vue.set()来进行响应式的数据更新
- Vue不能检测以下变动
- vm.list[0]=newValue
- vm.list.length = newLength
- property 的添加或移除
- 使用:
- Vue.set(target,index,newValue)
- vm.$set(vm.items, indexOfItem, newValue)
- 注:vue不允许添加根级响应式属性,只可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性
数据监测的原理
- vue会监视data中所有层次的数据
- 如何监测对象中的数据?
- 通过setter实现监视,且要在new Vue时就传入要监测的数据
- 对象中后追加的属性,Vue默认不做响应式处理
- 如需给后添加的属性做响应式,请使用如下API:
- Vue.set(target,propertyName/index,value) 或
- vm.$set(target,propertyName/index,value)
- 如何监测数组中的数据?
- 通过包裹数组更新元素的方法实现,本质就是做了两件事:
- 调用原生对应的方法对数组进行更新。
- 重新解析模板,进而更新页面。
- 通过包裹数组更新元素的方法实现,本质就是做了两件事:
- 在Vue修改数组中的某个元素一定要用如下方法:
- 使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
- Vue.set() 或 vm.$set()
- 特别注意:Vue.set() 和 vm.$set() 不能给vm或vm的根数据对象添加属性
收集表单数据
- type=”text”,则v-model收集的是value值,用户输入的就是value值
- type=”radio”,则v-model收集的是value值,且要给标签配置value值
- type=”checkbox”
- 没有配置input的value属性,那么收集的就是checked
- 配置input的value属性:
- v-model的初始值是非数组,那么收集的就是checked
- v-model的初始值是数组,那么收集的的就是value组成的数组
- 备注:v-model的三个修饰符:
- lazy:失去焦点再收集数据
- number:输入字符串转为有效的数字
- trim:输入首尾空格过滤
过滤器
- 定义:对要显示的数据进行特定格式化后再显示
- 语法:
- 注册过滤器:
Vue.filter(name,callback) 或 new Vue{filters:{}}
- name: 过滤器的名字,filters里面定义过滤的函数
- 使用过滤器:
{{ xxx | 过滤器名}} 或 v-bind:属性 = "xxx | 过滤器名"
- 注册过滤器:
- 注:
- 过滤器也可以接收额外参数、多个过滤器也可以串联
- 并没有改变原本的数据, 是产生新的对应的数据
常用的指令
v-bind
: 单向绑定解析表达式, 可简写为 :xxxv-model
: 双向数据绑定v-for
: 遍历数组/对象/字符串v-on
: 绑定事件监听, 可简写为@
v-if
: 条件渲染(动态控制节点是否存存在)v-else
: 条件渲染(动态控制节点是否存存在)v-show
: 条件渲染 (动态控制节点是否展示)
内置指令
- v-text指令
- 作用:向其所在的节点中渲染文本内容
- 用法:在标签上使用v-text=”str”
- 与插值语法的区别:v-text会替换掉节点中的内容,则不会
- 作用:向其所在的节点中渲染文本内容
- v-html指令
- 作用:向指定节点中渲染包含html结构的内容
- 用法:在标签上使用v-html=”str”
- 与插值语法的区别:
- v-html会替换掉节点中所有的内容,则不会
- v-html可以识别html结构。
- 严重注意:v-html有安全性问题!!!
- 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击
- 一定要在可信的内容上使用v-html,不要用在用户提交的内容上
- cookie本质是字符串
- v-cloak指令
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出的问题
- 用法:在标签上使用v-cloak
- v-once指令
- v-once所在节点在初次动态渲染后,就视为静态内容
- 数据的改变不会引起v-once所在结构的更新,可以用于优化性能
- 用法:在标签上使用v-once
- v-pre指令
- 跳过其所在节点的编译过程
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译
- 用法:在标签上使用v-pre
自定义指令
- 定义语法
- 局部指令:new Vue({ directives: {指令名:配置对象/回调函数} })
- 全局指令:Vue.directive(指令名,配置对象/回调函数)
- 配置对象中常用的3个回调:
- bind:指令与元素成功绑定时调用
- inserted:指令所在元素被插入页面时调用
- update:指令所在模板结构被重新解析时调用
- 注:
- 指令定义时不加v-,但使用时要加v-
- 指令名如果是多个单词,要使用kebab-case命名方式
生命周期
- 定义:Vue在关键时刻帮我们调用的一些特殊名称的函数。生命周期函数中的this指向是vm 或 组件实例对象。
- 常用的生命周期钩子
- mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
- beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】
- 关于销毁Vue实例
- 销毁后借助Vue开发者工具看不到任何信息
- 销毁后自定义事件会失效,但原生DOM事件依然有效
- 一般不会在beforeDestroy操作数据,因为即便操作数据,也不会再触发更新流程
非单文件组件
- Vue中使用组件的三大步骤:
- 定义组件(创建组件)
- 使用Vue.extend(options),其中options和new Vue()时的options相似,但也有区别
el不要写
,最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器data必须写成函数
,避免组件被复用时,数据存在引用关系
- 使用Vue.extend(options),其中options和new Vue()时的options相似,但也有区别
- 注册组件
- 局部注册:new Vue的时候传入components选项
- 全局注册:Vue.component(‘组件名’,组件)
- 使用组件(写组件标签)
<school></school>
- 定义组件(创建组件)
- 示例:
1
2
3
4
5
6
7
8
9
10// 创建
const school = Vue.extend({
template:`<div>......</div>`,
data(){
return {} //这里定义的变量是template中使用的
},
methods:{}
})
// 注册
Vue.component('school',school) - 注:
- 组件名写法:kebab-case命名 或 CamelCase命名(需要Vue脚手架支持)
- 组件标签:不使用脚手架时,
<school/>
会导致后续组件不能渲染 - 简写方式:
- const school = Vue.extend(options)
- 可简写为:const school = options
VueComponent
- 组件本质是一个VueComponent的构造函数,且不是自定义的,是Vue.extend生成的
- 组件标签是Vue解析时会创建的实例对象,即Vue执行new VueComponent(options)
- 每次调用Vue.extend,返回的都是一个全新的VueComponent
- this指向:
- 组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数,this均是
VueComponent实例对象
- new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数,this均是
Vue实例对象
- 组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数,this均是
- VueComponent的实例对象,简称vc;Vue的实例对象,简称vm
- 内置关系:
VueComponent.prototype.__proto__ === Vue.prototype
- 让组件实例对象(vc)可以访问到 Vue原型上的属性、方法
单文件组件
- 直接引用