VUE理解
vue是一套构建用户界面的渐进式自底向上增量开发的MVVM框架。VUE核心是为解决数据绑定问题,开发大型单页面应用和组件化只关注视图层。 核心思想:
- 数据驱动(视图的内容随着数据的改变而改变)
- 组件化(可以增加代码的复用性,可维护性,可测试性提高开发效率,方便重复使用,体现了高内聚低耦合)
vue的单向数据流
父级prop的更新会向下流动到子组件中,每次父组件发生更新,子组件所有的prop都会刷新为最新的值。数据从父组件传递给父组件,只能单向绑定,子组件内部不能直接修改父组件传递过来的数据。(可以用data和computed解决)
vue常用的修饰符
修饰符:
- .lazy:改变后触发,光标离开input输入框的时候值才会改变
- .number:将输出字符串转为number类型
- .trim:自动过滤用户输入的首尾空格 事件修饰符
- .stop:阻止点击事件冒泡(相当于event.stopPropagation)
- .prevent:防止执行预设的行为(event.preventDefault)
- .capture:添加事件监听器时使用事件捕获模式,先触发有该事件修饰符的
- .self:只会触发自己范围内的事件,不包括子元素
- .once:只执行一次 键盘修饰符:
- .enter
- .tab
- .esc
- .space
- .up
- .down
- .left
- .right 系统修饰符
- .ctrl
- .alt
- .shift
- .meta
VUE的生命周期
生命周期钩子函数
vue实例创建阶段
beforeCreate
vue实例刚在内存中创建,this变量不能使用,数据对象(data)和方法(methods)未初始化,watcher中的事件不能获取到
created
实例已经在内存中创建好,数据和方法已经初始化完成,但是模板未编译,页面无内容。不能操作dom节点(除非用this.$nextTick(function({})),在回调函数中操作dom),this.$el和this.$ref.xxx是undefined
beforeMounte
找到template模板,编译成render函数,转换成虚拟dom。模板编译完成,数据未挂载到页面,可以看到标签间的双花括号。
render:h=>h(App)
在beforeMounte之后和mounted之前,还有渲染render函数,它的作用是把模板渲染成虚拟dom。
mounted
模板编译完成,虚拟dom渲染成真正的dom标签,数据渲染到页面,vue实例在内存中创建完毕。一般在mounted中渲染从后端获取的数据。
VUE实例运行阶段
beforeUpdate
数据依赖改变或者用/$forceUpdate强制刷新时,对象data中的数据已经更改,虚拟dom已经重新渲染,但是页面的值还没有改变。
update
data中的数据和页面更新完毕,页面已经被重新渲染。在实际开发中,一般会用监听器watch来代替beforeUpdate和update,因为watch知道是哪一个数据发生变化。
VUE实例销毁阶段
beforeDestroy
实例销毁前使用,实例还是可用的
destroyed
VUE实例被销毁,观察者、子组件、事件监听被清除(页面数据不会消失,响应式失效)
new VUE后发生的事情
- new VUE会调用vue原型链上的_init方法对vue实例进行初始化
- .initLifecycle初始化生命周期,对vue实例内部的一些属性(如children、parent、isMounted)进行初始化
- .initEvents,初始化当前实例上的一些自定义事件(vue.$on)
- .initRender,解析slots绑定在vue实例上,绑定createElement方法在实例上
- 完成对生命周期,自定义事件等一系列属性的初始化后,触发生命周期钩子beforeCreate
- .initInjections,在初始化data和props之前完成依赖注入
- .initState,完成对data和props的初始化,同时对属性完成数据劫持,内部启用监听者对数据进行监听。
- .initProvide,对依赖注入进行解析
- 完成对数据(state状态)的初始化,触发生命周期钩子created
- 进入挂载阶段,将vue模板语法通过vue-loader解析成虚拟DOM树,虚拟DOM树与数据完成双向绑定,触发生命周期钩子beforeMount
- 将解析好的虚拟DOM树通过vue渲染成真实DOM,触发生命周期钩子mounted
VUE项目列表组件中key的作用
VUE采用diff算法对比新旧虚拟节点,从而更新节点。在VUE的diff函数交叉对比中,新节点和旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,找到响应的节点(key=>index 映射)。未找到就认为是一个新增节点。没有key就会遍历查找找到对应的旧节点。map映射比遍历查找速度快 key是vnode的唯一ID,可以依靠key更准确更快的拿到oldVode中对应的vnode节点
VUE子组件为什么不可以修改父组件传递的Prop
- 原因:单向数据流易于监测数据的流动,出现错误可以更快定位到错误发生的位置
如何监控属性修改给出警告的(setter)
初始化属性,在defineReactive时判断是否处在开发环境。如果是开发环境,在触发set时判断key是否处于updatingChildren中被修改,如果不是,说明此修改来自子组件,触发warning提示。 子组件修改的prop属于基础类型时会触发提示,无法修改父组件的数据源。基础类型赋值是值拷贝。将非基础类型赋值到key时也会触发提示,修改object的属性不会触发提示,并且会修改父组件数据源的数据。
VUE双向数据绑定原理
vue通过双向数据绑定,来实现view和model的同步更新。vue的双向数据绑定主要是通过数据劫持和发布订阅模式实现的。 通过Object.defineProperty()方法来对Model数据各个属性添加访问器属性,以此实现数据劫持。当model的数据变化时,通过配置setter和getter实现对View数据更新的通知。 对文本节点的更新,使用发布订阅模式,将属性作为一个主题。为该节点设置一个订阅者对象,将这个订阅者对象加入属性主题的订阅者列表中。当model层数据发生改变时,model作为发布者向主题发出通知,主题收到通知后再向它的所有订阅者推送,订阅者收到通知后更改自己的数据。 VUE3.0采用了Proxy。
VUE的响应式原理中Object.defineProperty有什么缺陷?
- Object.defineProperty无法监控到数组下标和长度的变化,导致通过数组下标添加元素,不能实时响应
- Object.defineProperty只能劫持对象的属性,需要对每个对象,每个属性进行遍历。如果属性值是对象,需要深度遍历。Proxy可以劫持整个对象,并返回一个新的对象。
- Proxy不仅可以代理对象,还可以代理数组,和动态增加的属性。
v-text、{{}}、v-html区别
{{}}和v-text将数据解析为纯文本,不能输出html,v-html可以渲染出html。
v-text指令:操作网页元素中的纯文本内容。{{}}是另一种写法
v-text与{{}}等价,{{}}叫模板插值,v-text叫指令。
在渲染数据多的时候,可能把大括号显示出来(屏幕闪动)
VUE组件间如何通信?
父子组件通信
- props+emit
- $refs+$parent
- provider+inject
兄弟组件通信
- eventBus
- $parent $ refs
任意组件通信
vuex
v-if和v-show有什么区别
v-if
真正的条件渲染,当条件为真时才会渲染。切换时会直接对标签进行创建或销毁,不显示的标签不会加载在DOM树中。
v-show
总是渲染。切换时对标签的display属性进行切换,通过display不显示来隐藏元素。 v-if的性能开销会比v-show大,切换频繁的标签更适合使用v-show。
VUE中computed和watch的差异
- computed是计算一个新的属性,并将该属性挂载到VUE实例上,而watch是监听已经存在且已挂载到VUE实例上的数据,所以用watch同样可以监听computed计算属性的变化。
- computed本质是惰性求值的观察者,具有缓存性。只有在依赖变化后第一次访问computed值,才会计算新的值。watch是当数据变化就会调用执行函数。
- 计算属性内不支持异步操作,侦听属性内支持异步操作。
- computed的函数中都有一个get(默认,获取计算属性)和set(手动添加,设置计算属性)方法。watch属性的值可以是一个对象,接收handler回调,deep,immediate三个属性。监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些其他事情。
- 使用场景:computed适用一个数据被多个数据影响,watch适合一个数据影响多个数据。
keep-alive组件有什么作用
keep-alive是vue的内置组件
※vue-router路由有哪些模式?
hash
后面的hash值变化,浏览器既不会服务器发出请求,也不会刷新。每次hash值得变化会触发hashchange事件。
history
利用H5中新增的pushState()和replaceState()方法。这两个方法应用于浏览器的历史记录栈,在当前已有的back,forward,go的基础之上,它们提供了对历史记录进行修改的功能。当它们执行修改时,虽然改变了当前的URL,但是浏览器不会立即向后端发送请求。
vue-cli项目中assets和static文件夹有什么区别?
共同点:都是用于存放项目中所使用的静态资源文件的文件夹 区别:assets中的文件在运行npm run build的时候会打包(压缩体积,代码格式化等)。打包之后会放到static中,static中的文件不会被打包。