中
1 Vue2.0响应式数据原理
总体思路是数据劫持+观察者模式
对象内部使用defineReactive方法,使用Object.defineProperty来劫持属性(只有现有的属性才会被劫持),数组是通过重写数组方法来实现的。当页面使用对应的属性时,每个属性都有自己的dep属性,该属性存储了它所依赖的watcher(依赖集合)。当属性发生变化时,会通知对应的watcher进行更新(分发更新)。
相关代码如下
class Observer {
// 观测值
constructor(value) {
this.walk(value);
}
walk(data) {
// 对象上的所有属性依次进行观测
let keys = Object.keys(data);
for (let i = 0; i < keys.length; i++) {
let key = keys[i];
let value = data[key];
defineReactive(data, key, value);
}
}
}
// Object.defineProperty数据劫持核心 兼容性在ie9以及以上
function defineReactive(data, key, value) {
observe(value); // 递归关键
// --如果value还是一个对象会继续走一遍odefineReactive 层层遍历一直到value不是对象才停止
// 思考?如果Vue数据嵌套层级过深 >>性能会受影响
Object.defineProperty(data, key, {
get() {
console.log("获取值");
//需要做依赖收集过程 这里代码没写出来
return value;
},
set(newValue) {
if (newValue === value) return;
console.log("设置值");
//需要做派发更新过程 这里代码没写出来
value = newValue;
},
});
}
export function observe(value) {
// 如果传过来的是对象或者数组 进行属性劫持
if (
Object.prototype.toString.call(value) === "[object Object]" ||
Array.isArray(value)
) {
return new Observer(value);
}
}
2 Vue 中如何检测数组变化
出于性能原因,数组不使用defineProperty来截取数组的每个元素。而是选择重写7个数组方法(push、shift、pop、splice、unshift、sorting、reverse)(AOP切片思想)
所以无法监听到Vue中改变数组的索引和长度。必须通过上述7种变异方法修改矩阵,才能触发矩阵对应的watcher的更新
相关代码如下
// src/obserber/array.js
// 先保留数组原型
const arrayProto = Array.prototype;
// 然后将arrayMethods继承自数组原型
// 这里是面向切片编程思想(AOP)--不破坏封装的前提下,动态的扩展功能
export const arrayMethods = Object.create(arrayProto);
let methodsToPatch = [
"push",
"pop",
"shift",
"unshift",
"splice",
"reverse",
"sort",
];
methodsToPatch.forEach((method) => {
arrayMethods[method] = function (...args) {
// 这里保留原型方法的执行结果
const result = arrayProto[method].apply(this, args);
// 这句话是关键
// this代表的就是数据本身 比如数据是{a:[1,2,3]} 那么我们使用a.push(4) this就是a ob就是a.__ob__ 这个属性就是上段代码增加的 代表的是该数据已经被响应式观察过了指向Observer实例
const ob = this.__ob__;
// 这里的标志就是代表数组有新增操作
let inserted;
switch (method) {
case "push":
case "unshift":
inserted = args;
break;
case "splice":
inserted = args.slice(2);
default:
break;
}
// 如果有新增的元素 inserted是一个数组 调用Observer实例的observeArray对数组每一项进行观测
if (inserted) ob.observeArray(inserted);
// 之后咱们还可以在这里检测到数组改变了之后从而触发视图更新的操作--后续源码会揭晓
return result;
};
});
3 你用过vue3.0吗?你知道多少
-
响应原理的变化 Vue3.x 使用 proxy 替换 Vue2.x 版本的 Object.defineProperty
-
组件选项声明方法 Vue3.x 使用 Composition API 布局是 Vue3.x 中的新选项。它是在组件中使用 Composition API 的门户。
-
模板语法轨道的变化称为轨道语法适配指令v模型升级
-
其他更改 Suspense 支持 Fragment(多个根节点)和 Protal(在域的其他部分渲染组件内容),并针对一些特殊场景进行了解决。基于treeshaking优化,有几个内置函数可用。
Vue3.0新特性及用户体验总结传送门
4 Vue3.0和2.0响应式原理区别
Vue3.x 使用代理而不是 Object.defineProperty。因为Proxy可以直接监听对象和数组的变化,而且拦截方式多达13种。
相关代码如下
import { mutableHandlers } from "./baseHandlers"; // 代理相关逻辑
import { isObject } from "./util"; // 工具方法
export function reactive(target) {
// 根据不同参数创建不同响应式对象
return createReactiveObject(target, mutableHandlers);
}
function createReactiveObject(target, baseHandler) {
if (!isObject(target)) {
return target;
}
const observed = new Proxy(target, baseHandler);
return observed;
}
const get = createGetter();
const set = createSetter();
function createGetter() {
return function get(target, key, receiver) {
// 对获取的值进行放射
const res = Reflect.get(target, key, receiver);
console.log("属性获取", key);
if (isObject(res)) {
// 如果获取的值是对象类型,则返回当前对象的代理对象
return reactive(res);
}
return res;
};
}
function createSetter() {
return function set(target, key, value, receiver) {
const oldValue = target[key];
const hadKey = hasOwn(target, key);
const result = Reflect.set(target, key, value, receiver);
if (!hadKey) {
console.log("属性新增", key, value);
} else if (hasChanged(value, oldValue)) {
console.log("属性值被修改", key, value);
}
return result;
};
}
export const mutableHandlers = {
get, // 当获取属性时调用此方法
set, // 当修改属性时调用此方法
};
5 Vue父子组件生命周期钩子函数执行顺序
- 加载渲染进程
创建前的父级->创建父级->挂载前的父级->创建前的子级->创建子级->安装前的子级->安装子级->安装父级
- 子组件 的更新流程
更新前的父级->更新前的子级->子级更新->父级更新
- 父组件 的更新过程
父更新前->父更新
- 销毁过程
父级销毁前->子级销毁前->子级销毁->父级销毁
6 什么是虚拟DOM,它的优缺点是什么
因为在浏览器中操作 DOM 的成本很高。频繁使用 DOM 会导致一定的性能问题。这就是 Virtual Dom 发挥作用的地方。 Vue2的Virtual DOM借鉴了开源库snabbdom的实现。 Virtual DOM 的本质是使用原生 JS 对象来描述 DOM 节点,它是真实 DOM 的抽象。
优点:
-
保证的性能下限:框架的虚拟DOM必须适应上层API可以生成的所有操作。一些 DOM 操作的实现必须是通用的,因此性能并不是最优的;但相比原始DOM操作性能要好很多,所以框架的虚拟DOM至少可以保证你在不进行手动优化的情况下仍然可以提供良好的性能,即保证性能的下界;
-
无需手动操作DOM:我们不再需要手动操作DOM。我们只需要编写View-Model的代码逻辑即可。框架会双向绑定虚拟DOM和数据,帮助我们以可预测的方式更新视图,非常方便。显着提高我们的开发效率;
-
跨平台:虚拟DOM本质上是一个JavaScript对象,DOM与平台强相关。相比之下,虚拟DOM可以进行更实用的跨平台操作,比如服务端渲染、weex开发等
-
无法进行极致优化:虽然虚拟DOM+合理优化足以满足大部分应用的性能需求,但在一些性能要求极高的应用中,虚拟DOM无法优化到极致。
-
第一次渲染大量DOM时,由于多了一层虚拟DOM计算,会比插入innerHTML慢。
- text和textarea元素使用value属性和输入事件;
- 复选框和单选按钮使用选中属性和更改事件;
- 选择字段将值作为属性,将更改作为事件。
- 导航已触发。
- 在禁用组件中的RouteLeave守卫之前调用。
- 在每次轮班前调用全局。
- 在重用组件中调用 beforeRouteUpdate 守卫(2.2+)。
- 进入路由配置之前先调用。
- 解析异步路由组件。
- 在激活的组件中调用beforeRouteEnter。
- 在 Solution Guard (2.5+) 之前调用全局。
- 导航已确认。
- 调用全局 afterEach 钩子。
- 触发 DOM 更新。
- 调用beforeRouteEnter守卫中传递给next的回调函数,创建的组件实例将作为参数传递给回调函数。
- State:定义应用程序状态的数据结构,可以指定默认的启动状态。
- Getters:允许组件从存储中检索数据,mapGetters 辅助函数只是将存储中的 getters 映射到本地计算属性。
- Mutation:它是改变store中状态的唯一方法,并且它必须是同步函数。
- Action:用于提交突变而不是直接更改状态,并且可以包含任何异步操作。
- 模块:允许将单个store分为多个store并同时存储在单个状态树中。
- 不要将不需要响应的数据放入data中(可以使用Object.freeze()来冻结数据)
- v-if 和 v-显示单独的使用场景
- 计算并查看区分使用场景
- v-for遍历必须加key,key最好是id值,避免同时使用v-if
- 大数据列表和表性能优化-虚拟列表/虚拟表
- 防止内部泄漏,组件销毁后销毁全局变量和事件
- 图片懒加载
- 路由器延迟加载 按需引入第三方插件
- 正确使用 keep-alive 缓存组件
- 防抖、沙哑应用
- 服务器端渲染或预渲染
缺点:
v 模型只是语法糖 v 模型内部使用不同的属性,并针对不同的输入元素引发不同的事件: 注意:对于需要使用输入法的语言(如中文、日文、韩文等),你会发现在组合文本的输入法过程中v-model不会更新。
如果不使用键,Vue 将使用一种最小化动态元素的算法,并尝试尽可能地修改/重用相同类型的元素。 key是Vue中vnode的唯一标记,通过这个key我们的diff操作可以更准确、更快 更准确:因为没有与key进行就地复用,所以在同一个Node函数a.key === b.key比较中可以避免就地复用。所以会更加准确。 更快:利用key的唯一性生成map对象来获取对应节点,比遍历方式更快 相关代码如下
原生事件绑定通过addEventListener绑定到真实元素,组件事件绑定通过Vue自定义的$on实现。如果要在组件上使用原生事件,需要添加 .native 修饰符,相当于将子组件当成父组件中的常规 html 标签,然后添加原生事件。 on、on、on、emit都是基于发布订阅模型,维护一个事件中心。开启后,事件按名称存储在事件中心,称为订阅者,然后发出相应的事件来执行事件中心相应的监听器 路由钩子的执行流程。钩子函数的类型有:全局防护、路由防护、组件防护 完整的导航分析流程:
我们经常需要将与某个模式匹配的所有路由映射到同一个组件。例如,我们有一个用户组件,它为具有不同 ID 的所有用户呈现。接下来我们可以在vue router的路由路径中使用“动态分段”来达到这样的效果: 问题:复用vue router组件导致路由参数失效怎么办? 解决方案: 1。通过watch监听路由参数然后发送请求 2。使用 :key 防止“重复使用” vuex是专门针对vue的全局状态管理系统,用于多个组件之间的数据共享和数据缓存。 (不能坚持,核心内部原理是创建全局实例new Vue) 主要包括以下模块: 需要做vuex数据持久化通常使用本地存储方案来存储数据,可以设计自己的存储方案,或者使用第三方插件 推荐使用vuex-persist插件,这是Vuex持久化存储的插件。无需手动访问存储,而是直接将状态保存到cookie或本地存储 Module:由于使用了单一的状态树,应用程序的所有状态都会集中到一个比较大的对象中。当应用程序变得非常复杂时,存储对象可能会变得非常臃肿。为了解决上述问题,Vuex 允许我们将 store 拆分为模块。每个模块都有自己的状态、突变、操作、getter,甚至嵌套子模块。 命名空间:默认情况下,模块内的操作、突变和 getter 会在全局命名空间中注册 - 这允许多个模块响应相同的突变或操作。如果你希望你的模块有更高程度的封装性和可重用性,可以通过添加namespace: true使其成为命名空间模块。当一个模块被注册时,它的所有 getter、action 和mutations 都会根据模块注册的路径自动命名。 SSR是服务器端渲染,也就是说Vue将标签渲染到客户端HTML并在服务器端完成,然后将html直接返回给客户端。 优点: SSR 具有更好的 SEO 和更快的可见部分 缺点:开发条件会受到限制。服务端渲染只支持两个钩子,Create之前和created。当我们需要一些外部扩展库时,需要特殊处理。服务器端渲染应用程序也必须在 Node.js 中。操作环境。 仆人将有更大的负载要求 1。工厂模式——传入参数创建实例 虚拟DOM根据不同参数将Vnode返回为基础标签和组件Vnode 2。单例模式——整个程序只有一个实例 vuex和vue-router插件注册方法安装判断如果系统中有实例则直接返回 3.发布订阅模式(vue事件机制) 4。观察者模式(响应式数据原理) 5。装饰模式:(@Dekoratorbruk) 6。策略模式策略模式是指对象有特定的行为,但在不同的场景下该行为有不同的实现方案——比如替代品的合并策略 ...其他mod欢迎补充 这里只展示Vue的性能优化。整个项目的性能优化是一个大工程。你可以再写一篇关于性能优化的文章哈哈 面试前要认真做好准备。你需要准备好简历上写的知识点和原理。多思考项目的难点和亮点。这就是你在面试时与其他人不同的地方。 是为了表现他的谦虚和好学,以及他对未来不断进步的计划。公司在招聘时更喜欢稳定的人。 万事开头难,但是在程序员的道路上坚持几年,还是有很大的发展空间的,全靠坚持。 为了帮助您更好、更高效地准备面试,我们特意整理了《前端工程师面试手册》的电子稿件文件。 前端面试问题总结 JavaScript 性能 linux 前端数据汇总 前端工程岗位缺口一直很大,符合岗位要求的人越来越少,所以学前端的朋友要注意了,一定要学扎实的技能,做有价值的项目,这样才会更顺利找到工作工作 无论什么情况,问题都不会很大。
7 v型原理
组件 <input v-model="sth" /> //这一行等于下一行
<input v-bind:value="sth" v-on:input="sth = $event.target.value" />
<currency-input v-model="price"></currentcy-input>
<!--上行代码是下行的语法糖
<currency-input :value="price" @input="price = arguments[0]"></currency-input>
-->
<!-- 子组件定义 -->
Vue.component('currency-input', {
template: `
<span>
<input
ref="input"
:value="value"
@input="$emit('input', $event.target.value)"
>
</span>
`,
props: ['value'],
})
8 v-for 为什么添加密钥
9 Vue事件的绑定原理
10 vue-router的routinghook功能是什么,执行顺序是什么
11 什么是vue-router动态路由?有什么问题
const User = {
template: "<div>User</div>",
};
const router = new VueRouter({
routes: [
// 动态路径参数 以冒号开头
{ path: "/user/:id", component: User },
],
});
watch: { //通过watch来监听路由变化
"$route": function(){
this.getData(this.$route.params.xxx);
}
}
<router-view :key="$route.fullPath" />
复制代码
12 说说我个人对vuex的理解
13 Vuex页面更新数据丢失如何解决
14 为什么Vuex必须拆分成模块并添加命名空间
14 你用过Vue SSR吗?说说SSR
16 vue中使用了哪些设计模式
17 你做过哪些Vue性能优化
对象层次不宜太深,否则性能会很差
总结一下
完整版PDF免费分享,只要您喜欢并支持,点击这里免费获取。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。