1,mixin混入(vue3弃用)
参考:Vue 混入(mixin)详细介绍(可复用性、全局混入)_vue mixin_前端不释卷leo的博客-CSDN博客
-
定义mixin内容,然后导出。一个混入对象可以包含任意组件选项(如data、methods、mounted等等)。
-
组件中用mixins:[ ],使用mixin内容
-
当mixin内容和组件内容有重复时,不冲突的合并,冲突的以组件数据为主。
-
1.对于created,mounted 等生命周期函数 mixin文件中的代码先执行,组件中的后执行
2.对于data中定义的字段,组件中定义组件覆盖mixin中同名字段
3.对于 method中的同名方法,组件内的同名方法覆盖mixin中的方法 - 全局混入,在main文件中,引入,Vue.mixin(mixin)
2,Vue全局API
- Vue.use,安装插件。
- Vue.mixin,混入。
-
Vue.directives,定义指令。
-
Vue.filter,定义过滤器。
-
(vue.extend的使用场景,vue.component和vue.extend的使用方法和区别)
-
Vue.component,定义组件。
- Vue.extend,组件构造器。data 选项必须是函数。
-
<div id="box"></div> // 创建构造器 var test = Vue.extend({ template: '<p>{{id}}</p>', data: function () { return { id: '999', } } }) // 创建 test 实例,并挂载到一个元素上。 new test().$mount('#box')
- Vue.set,因为Vue2中使用object.defineProperty无法检测到响应式数据中直接添加的property,可以使用Vue.set添加property,确保视图更新。(具体)
-
// 方式一 Vue.set(源数据,要修改的键,新值) // 方式二:使用this或vm的Vue实例对象 vm.$set(源数据,要修改的键,新值)
- Vue.delete,删除对象的 property。如果对象是响应式的,确保删除能触发更新视图。
- Vue.nextTick,在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。(具体,使用场景)
3,keep-alive
参考:Vue中 keep-alive 详解_vue keep-alive_明天也要努力的博客-CSDN博客
keep-alive是vue内置组件,自身不会渲染成一个 DOM 元素。
作用:在组件切换过程中将状态保留在内存中,防止重复渲染DOM,减少加载时间及性能消耗,提高用户体验性。
原理:在 created 函数调用时将被包裹的组件的VNode节点保存在this.cache中,在页面再渲染时,根据使用 include 和 exclude 设置的名称或者状态,判断如果符合条件则从this.cache中取出之前缓存的 VNode 实例进行渲染。(不用完全渲染dom,而是直接使用之前的虚拟dom渲染?)
属性:include(组件名匹配时,缓存,可以设为动态属性,可以进行if判断)
exclude(组件名匹配时,不缓存)
max(最多缓存多少组件实例)(具体使用,什么意思)
钩子函数:被包裹的组件多出两个钩子函数,activated,deactivated函数。
activated:在组件被激活时调用,在组件第一次渲染时也会被调用,之后每次keep-alive激活时被调用。使用< keep-alive > 会将数据保留在内存中,如果要在每次进入页面的时候获取最新的数据,需要在 activated 阶段获取数据,承担原来created钩子中获取数据的任务。
deactivated:在组件被停用时调用。
钩子函数顺序:当引入keep-alive 的时候,页面第一次进入,钩子的触发顺序 created -> mounted -> activated,退出时触发 deactivated。当再次进入(前进或者后退)时,只触发 activated。
应用:
- 当从主页跳转列表页时,列表页组件重新渲染;
- 当从详情页返回列表页时,列表页组件缓存,不重新请求数据;
4,vue中的data为什么是一个函数?起到什么作用?
参考:vue中的data为什么是一个函数?起到什么作用?_vue中的data为什么写成函数_用十年奋斗.я的博客-CSDN博客
函数返回值形式,复用组件时,使用组件时会返回一份新的data,data数据互不影响。
如果使用对象形式,data中存储的都是内存的同一个地址,复用组件时,每个组件公用同一份data,data数据会互相影响。
5,Vue data 中某一个属性的值发生改变后,视图会立即同步执行重新渲染吗?
不会立即同步执行重新渲染。Vue实现响应式并不是数据发生变化之后DOM立即变化,而是按一定的策略进行DOM的更新。Vue在更新DOM时是异步执行的。只要侦听到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。
如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是非常重要的。然后,在下一个的事件循环tick中,Vue刷新队列并执行实际(已去重的)工作。(?)
6,Vue2如何检测数组变化?
重写数组的push、pop、shift、unshift、splice、sort、reverse七种方法。重写方法在实现时除了将数组方法名对应的原始方法调用一遍并将执行结果返回外,还通过执行ob.dep.notify()将当前数组的变更通知给其订阅者,这样当使用重写后方法改变数组后,数组订阅者会将这边变化更新到页面中。
7,axios封装和使用
fetch和get和post使用
8, scoped
参考:Vue中的scoped实现原理和样式穿透方法及原理_vue scoped原理_cc° 淡忘的博客-CSDN博客
原理:
1.为组件实例生成一个唯一标识,给组件中的每个标签对应的dom元素添加一个唯一的标签属性data-v-xxxx
2.给<style scoped>中的每个选择器的最后一个选择器添加一个属性选择器,原选择器[data-v-xxxx],如:原选择器为.container #id div,则更改后选择器为.container #id div[data-v-xxxx]
样式穿透:引用了第三方组件后,需要在组件中局部修改第三方组件的样式,而又不想去除scoped属性造成组件之间的样式污染。此时只能通过特殊的方式,穿透scoped。
样式穿透原理:scoped后选择器最后默认会加上当前组件的一个标识,比如[data-v-49729759]
用了样式穿透后,在deep之后的选择器最后就不会加上标识。
1.>>>
/* 如果项目使用的是css原生样式,那么可以直接使用 >>> 穿透修改 */
div >>> .cla {
color: red;
}
2./deep/
//项目中用到了预处理器 scss 、sass、less 操作符 >>> 可能会因为无法编译而报错
//可以使用 /deep/ (注意:vue-cli3以上版本不可以)
div /deep/ .cla {
color: red;
}
3.::v-deep (css使用拓展语言dart-sass, 需要使用 ::v-deep 深度选择器来修改 外用第三方组件的样式,dart-sass不支持 /deep/ 和 >>> 的写法)
/* 用法: */
div ::v-deep .cla {
color: red;
}
9,单页面应用SPA(Single Page Application)
单页面应用指一个系统只加载一次资源,然后之后的操作交互、数据交互是通过js代码来调用router、ajax等来进行,页面并没有刷新,页面只在最开始前刷新一次。
优点:
用户体验好、快,内容的改变不需要重新加载,提升了用户体验;
前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方式更加规范化,便于修改和调整。
缺点:
1.首次加载耗时较多,需加载大量的资源(采用按需加载,缓存,懒加载)
2.导航不可用,由于单页Web应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能(配置好路由信息,通过记录浏览过的历史路由信息,可以很好的记录或历史查看过的界面,也可以独立写个足迹功能实现。)
3.对搜索引擎(SEO)不友好
SEO不友好的原因:视图和内容都是通过本地JavaScript来组织和渲染。而搜索搜索引擎抓取的内容,需要有完整的HTML和内容(搜索引擎只认识html里的内容,不认识js的内容)单页应用架构的站点,并不能很好的支持搜索,会导致单页应用做出来的网页在百度和谷歌上的排名差。
在处理单页应用的时候页面是不刷新的,所以会导致我们的网页记录和内容很难被搜索引擎抓取到。
解决方法:解决的方法是用 #!号代替#号,因为谷歌会抓取带有#!的URL。(Google规定,如果你希望Ajax生成的内容被浏览引擎读取,那么URL中可以使用"#!"(这种URL在一般页面一般不会产生定位效果)
10,mvvm和mvc和mvp(分别是什么,优缺点)
三个架构模式,为了责任分离,分层结构,方便维护。可维护性高,
1.mvc:
早期是后端模式,model(数据层)-- view(视图层) -- controller(控制器)
Controller负责将Model的数据用展示在视图层,换句话说就是在Controller里面把Model的数据赋值给View。view通过事件通知controller,controller修改数据。而数据和视图存在映射关系。
接收参数,调用代码,控制页面跳转。
优点:强调责任分离,方便维护。
缺点:每次更新,都需要完成整个流程,方便维护,但是开发过程不够便捷。
2,mvp
p(presenter),model和view的中间人。负责m和v的数据交互。
m和v之间不能直接交流。但是随着开发,presenter体积越来越大,不方便维护。
3.mvvm
mvvm架构,使用vm解决presenter过于臃肿的问题。
dom listener监听,view改变model改变,通过事件监听来让视图中 用户交互行为可以通过事件来 修改model层数据。(这样就减少了直接的dom操作)
data binding绑定,采用响应式(绑定)机制,自动将数据变化转化为视图更新。
model改变view改变,组成了双向绑定。
11,响应式原理object.definProperty,(数据劫持,发布者和订阅者)
核心部件:1.Observer 2.Dep 3.Watcher
采用数据劫持 结合 发布者-订阅者模式 来实现数据的响应式
1,数据劫持:使用object.definProperty 把data属性转化成getter,setter方法。
当访问属性时触发get方法,修改属性时触发set方法操作dom使视图更新。
缺点:
1,因为只能劫持对象的属性,如果属性值也是对象,就要深层遍历。大量的深层便利会导致调用栈溢出。
2,不能检测到对象的新增属性,删除属性。(为什么?)
(无法触发get,set方法)
3,无法正确监听到数组方法,无法监听到数组下标的变化,当使用数组下标赋值时,不能实时响应。(重写数组方法)
Vue通过Object.defineProperty的 getter/setter 对收集的依赖项进行监听,在属性被访问和修改时通知变化,进而更新视图数据;
Vue不支持IE8以下版本的浏览器,因为Vue是基于 Object.defineProperty 来实现数据响应的,而 Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因;
Vue数据响应式变化主要涉及 Observer, Watcher , Dep
Observer:
通过执行 observe(data, true / asRootData /)将所有data变成可观察的,即对data定义的每个属性进行getter/setter操作。
Observer类是将每个目标对象(即data)的键值转换成getter/setter形式,用于进行依赖收集以及调度更新。
遍历data所有的数据,进行getter/setter绑定, 若data为数组,先将 重写过的数组方法 替换原来的数组方法,重写过的数组方法可以被检测到变化,再进行绑定。
getter方法:
- 给每个data声明一个 Dep 实例对象,被用于getter时进行收集相关的依赖。即收集依赖的watcher。
- 根据Dep.target来判断是否收集依赖,还是普通取值。
- 依赖收集简单点理解就是收集只在实际页面中用到的data数据,然后打上标记。(这里的标记就是打上Dep.target)。
setter方法:
- 先用getter获取值,进行比对。如果不一致,并且修改后的值没有setter方法则使用obsever,对这个属性进行getter/setter操作,保证数据响应式。
- 通过dep对象通知所有观察者去更新数据,从而达到响应式效果。
- setter操作时候通过dep去通知watcher,此时watcher就执行变化。
Watcher
Watcher是一个观察者对象。依赖收集以后Watcher对象会被保存在Dep的subs中,数据变动的时候Dep会通知Watcher实例,然后由Watcher实例执行回调进行视图的更新。
Dep
data中的数据在触发 getter 时,Dep 就会收集依赖的 Watcher ,在data变动时,就会通过 Dep 给 Watcher 发通知进行更新。
总结
- 在 Vue 中模板编译过程中的指令或者数据绑定都会实例化一个 Watcher 实例,实例化过程中会触发 get() 将自身指向 Dep.target;
- data在 Observer 时执行 getter 会触发 dep.depend() 进行依赖收集;依赖收集的结果:
- 1、data在 Observer 时闭包的dep实例的subs添加观察它的 Watcher 实例;
- 2. Watcher 的deps中添加观察对象 Observer 时的闭包dep;
- 当data中被 Observer 的某个对象值变化后,触发subs中观察它的watcher执行 update() 方法,最后实际上是调用watcher的回调函数cb,进而更新视图。
简言之,数据响应式的中心思想,是通过重写数据的 get 和 set 属性方法,让数据在被渲染时把所有用到自己的订阅者存放在自己的订阅者列表中,当数据发生变化时将该变化通知到所有订阅了自己的订阅者,达到重新渲染的目的。
三部分:让数据变成响应式、依赖收集 和 派发更新。
简言之,数据响应式的中心思想,是通过重写数据的 get 和 set 属性方法,让数据在被渲染时把所有用到自己的订阅者存放在自己的订阅者列表中,当数据发生变化时将该变化通知到所有订阅了自己的订阅者,达到重新渲染的目的。
vue初始化时,会给 data 赋值一个空对象并进行 observe
1,让数据变成响应式
调用 Observer 类构造方法
-
针对当前的数据对象新建一个订阅器;
-
为每个数据的 value 都添加一个__ob__属性,该属性不可枚举并指向自身;
-
针对数组类型的数据进行单独处理(包括赋予其数组的属性和方法,以及 observeArray 进行的数组类型数据的响应式);
-
this.walk(value),遍历对象的 key 调用 defineReactive 方法;
defineReactive 是真正为数据添加 get 和 set 属性方法的方法,它将 data 中的数据定义一个响应式对象,并给该对象设置 get 和 set 属性方法,其中 get 方法是对依赖进行收集, set 方法是当数据改变时通知 Watcher 派发更新。
2,依赖收集
依赖收集的原理是:当视图被渲染时,会触发渲染中所使用到的数据的 get 属性方法,通过 get 方法进行依赖收集。
依赖到底是什么?依赖要存放在哪里?这两部分刚好对应 Vue 中两个类,一个是 Watcher 类,而依赖就是 Watcher 类的实例;另一个是 Dep 类,而依赖存放在 Dep 实例的 subs 属性(数组类型)中进行管理。
在 Vue 中模板编译过程中的指令或者数据绑定都会实例化一个 Watcher 实例,组件 A 用到了数据 b,则组件 A 依赖数据 b,组件 A 的 watcher 会被添加到数据 b 的依赖数组 subs 中。也就是说如组件A 依赖 b,则将该组件的渲染 Watcher 作为订阅者加入 b 的订阅者列表中。
3,Dep - 订阅器
get 方法主要使用 depend 方法进行依赖收集,depend 是 Dep 类中的属性方法。
Dep 类中有三个属性:
target(全局唯一的静态数据依赖的监听器 Watcher)
id(该属性的 id)
subs(订阅这个属性数据的订阅者列表,另外还提供了将订阅者添加到订阅者列表的 addSub 方法、从订阅者列表删除订阅者的 removeSub 方法。)
4,派发更新
当我们修改一个存在 data 属性上的值时,会触发数据中的 set 属性方法,首先会判断并修改该属性数据的值,并触发自身的 dep.notify 方法开始更新派发:
通过对数据响应式这一部分的源码分析,可以看到 Vue 为了实现监听数据动态变化来进行对应的视图渲染和其他操作,为每一个数据都闭包了一个订阅者管理器,即 Dep 实例,并且为每一个对数据的依赖都创建了一个 Wathcer 实例作为订阅者存放在数据自己的订阅者列表 subs 中。渲染时通过数据中的 get 属性方法来收集依赖,数据更新时通过其 set 属性方法来通知到对应的 watcher 去做相应的更新操作或执行某个回调函数。
vue3中使用proxy实现响应式,支持监听对象新增属性,监听数组方法。
proxy是Es6中新增的一个特性
在目标对象之前设置一层"拦截",外界对该对象的访问,必须经过这层拦截,因此可以对外界的访问进行过滤和设置。
模板编译原理
可以看到,编译的主要过程为4步:
1、将template字符串 转为ast抽象语法树
2、优化ast抽象语法树
3、将抽象语法树 生成 字符串形式的 js代码
4、最后将生成的 函数字符串 转为render函数
实例和new vue,property是什么(原型链)
原型,和指向有什么用
生命周期,钩子函数,渲染流程(每一步调用什么函数,具体干了什么
在每个阶段能干什么,一般用来干什么)
v-model原理
在input输入框中绑定一个值
v-model其实是一个语法糖,他背后的本质上是包含两个操作
- v-bind绑定一个value属性
- v-on指令给当前元素绑定input事件
绑定一个值,就是使用v-bind绑定一个值
修改值并且实时响应,就是使用v-on绑定了一个事件,将修改后的值赋值给v-bind绑定的值
当input输入框使用value绑定默认值时,再使用v-model绑定值,和未设置value时一致。
这是因为,使用v-model后,表单控件显示的值只依赖所绑定的数据,不在关心初始时的value属性。 v-model 会忽略(优先级大于)所有表单元素的 value、checked、selected attribute 的初始值。
渐进式框架的理解,自底向上增量开发的设计
- 渐进式框架的大概意思就是你可以只用我的一部分,而不是用了我这一点就必须用我的所有部分。
按需引入,可以只使用自己想用的一部分功能。
大概就是你不必一开始就用Vue所有的全家桶,根据场景,官方提供了方便的框架供你使用。
SSR(Server-Side Rendering
)
1,传统服务端渲染SSR 2,单页面应用SPA 3,服务端渲染SSR
传统SSR是服务端渲染:在后台将vue实例渲染为HTML字符串直接返回,在前端激活为交互程序。
实现原理:
- 客户端发送请求给服务器
- 服务器查询数据库,使用视图、模板引擎等拼接成html字符串,返回给客户端
- 客户端渲染html
优点:
- 网页内容在服务器端渲染完成,一次性传输到浏览器,所以首屏加载速度非常快
- 有利于SEO,因为服务器返回的是一个完整的html,在浏览器可以看到完整的dom,对于爬虫、百度搜索等引擎就比较友好
缺点:
- 在后续跳转其它链接时,整个页面还要重复这样的操作,不断地请求响应、请求响应,相对来说,消耗的带宽资源、后续请求的时间就多了
vue2和vue3区别
1,实现响应式原理方法
2,Vue3支持碎片(Fragments),组件中可以有多个根节点
3,生命周期变化
4,vue3使用setup()返回data数据
setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之前的函数
执行 setup 时,组件实例尚未被创建(在 setup() 内部,this 不会是该活跃实例的引用,即不指向vue实例,Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)
注意事项:
1、setup函数中不能使用this。Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)
2、setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。但是,因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性。
如果需要解构 prop,可以通过使用 setup 函数中的toRefs 来完成此操作;