文章目录
-
-
-
- 1、vue的生命周期
- 2、Vue2.x 双向绑定原理
- 3、Vue3.x 响应式原理
- 4、v-for 为什么要加上 key
- 5、Vdom的理解
- 6、vuex 的结构,以及 actiion 和 mutation 的区别
- 7、axios 的原理以及优点,如何终止 axios 请求
- 8、vue 的缺点
- 9、vue 和 react 区别
- 10、computed 和 watch 区别,以及 computed 如何实现缓存和更新的
- 11、hash 和 history 区别 ,分别是怎么实现的
- 12、nextTick 作用和实现
- 13、solt 插槽种类以及原理
- 14、keep-alive使用和原理
- 15、MVVM 和 MVC
- 16、template 模板引擎的渲染过程
- 17、SPA页面的理解
- 18、vue 性能优化?
- 19、父子组件加载顺序
- 20、Vue.use是做什么的,原理是什么
- 21、Proxy 与 Object.defineProperty 优劣对比
- 22、v-model 的原理
- 23、v-if 和 v-show 的区别
- 24、v-for 和 v-if 优先级
- 25、Vue.mixin 使用场景和原理
- 26、Vue.set
- 27、组件中写 name 选项有哪些好处
- 28、vue 组件通讯有哪些方法
- 29、vue 组件的data 为什么是一个函数
- 30、data 里面数据量比较大如何优化
- 31、子组件里面可以修改父组件的值吗
- 32、生命周期钩子是如何实现的
- 33、什么是 vue-loader
- 34、vue 是怎么检测数组的变化的
- 35、vue 是怎样依赖收集的?(dep 和 Watcher 是什么关系)
- 36、vue路由的钩子函数(导航守卫)
- 37、vue $route 和 $router 的区别
- 38、vue 中的 diff 算法原理
- 39、Vue. extend 能做什么
- 40、vue 的 mixin 和 mixins 区别
- 41、vue 组件渲染和更新的过程
- 42、vue 为什么采用异步渲染
- 43、vue 为什么要使用异步组件
- 44、vue 如何快速定位那个组件出现性能问题的
- 45、vue3.x 对比 vue2.x 变化
- 46、watch 的 deep 如何实现的
- 47、v-html 会导致那些问题
- 48、v-el作用
- 48、说说vue的动态组件
- 49、怎么定义vue-router的动态路由?怎么获取传过来的值?
- 50、自定义指令
- 51、自定义过滤器
- 52、vue 中 extend、mixins、extends的区别
-
-
1、vue的生命周期
2、Vue2.x 双向绑定原理
vue 是通过 数据劫持 结合 发布者-订阅者 来实现双向绑定;数据劫持通过Object.defineProperty()方法的get和set方法来重新定义,set是设置属性值触发的函数,get是读取属性值触发的函数;
底层实现:
详细过程参考
3、Vue3.x 响应式原理
Vue3.x改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达13种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化。
Proxy只会代理对象的第一层,那么Vue3又是怎样处理这个问题的呢?
判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理, 这样就实现了深度观测。
监测数组的时候可能触发多次get/set,那么如何防止触发多次呢?
我们可以判断key是否为当前被代理对象target自身属性,也可以判断旧值与新值是否相等,只有满足以上两个条件之一时,才有可能执行trigger。
4、v-for 为什么要加上 key
function sameVnode (a, b) { return ( a.key === b.key && ( ( a.tag === b.tag && a.isComment === b.isComment && isDef(a.data) === isDef(b.data) && sameInputType(a, b) ) || ( isTrue(a.isAsyncPlaceholder) && a.asyncFactory === b.asyncFactory && isUndef(b.asyncFactory.error) ) ) ) }
5、Vdom的理解
vdom 就是用 js 对象来描述真实 DOM,虚拟DOM的实现就是普通对象包含tag、data、children等属性对真实节点的描述。(本质上就是在JS和DOM之间的一个缓存);由于直接操作 DOM 性能低,但是 js 层的操作效率高,可以将 DOM 操作转化成对象操作,最终通过diff算法比对差异进行更新DOM (减少了对真实DOM的操作)。虚拟DOM不依赖真实平台环境从而也可以实现跨平台。
优点:
缺点:
无法进行极致优化: 在一些性能要求极高的应用中虚拟DOM无法进行针对性的极致优化
6、vuex 的结构,以及 actiion 和 mutation 的区别
结构:state(初始化数据)、action(异步处理数据)、mutation(唯一能够修改state的操作)、getter(从state中动态获取相关数据)、module(模块化)
区别:
7、axios 的原理以及优点,如何终止 axios 请求
原理:属于 XMLHttpRequest,是一个基于 Promise 的 http 请求库,可用于浏览器和 Node
优点:
const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function(thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); }else { // 处理错误 } }); source.cancel('xxx');
2)、通过传递一个 executor 函数到CancelToken构造函数创建cancel token
const CancelToken = axios.CancelToken; let cancel axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c){ cancel = c }) }); cancel();
注意: executor 处理器函数接收两个函数 resolve 和 reject 作为参数,异步任务执行成功调用 resolve,否则调用reject。
8、vue 的缺点
9、vue 和 react 区别
相同:
不同:
10、computed 和 watch 区别,以及 computed 如何实现缓存和更新的
区别:
watch的参数:
deep:深度监听
immediate :组件加载立即触发回调函数执行
computed缓存原理:
conputed本质是一个惰性的观察者;当计算数据存在于 data 或者 props里时会被警告;
vue初次运行会对 computed 属性做初始化处理(initComputed),初始化的时候会对每一个 computed 属性用 watcher 包装起来 ,这里面会生成一个 dirty 属性值为 true;然后执行 defineComputed 函数来计算,计算之后会将 dirty 值变为 false,这里会根据 dirty 值来判断是否需要重新计算;如果属性依赖的数据发生变化,computed 的 watcher 会把 dirty 变为 true,这样就会重新计算 computed 属性的值。
11、hash 和 history 区别 ,分别是怎么实现的
区别:
原理:
hash:通过 onhashchange 事件监听 hash 变化,然后根据 hash 的变化更新页面部分内容(hash变化不会触发浏览器请求,但是会触发 hashchange 事件)。
history:主要是 H5 新增的两个 API(pushState、replaceState);他们可以改变url,但是不会发送请求,这样就可以通过 onpopstate 监听 url 变化来实现页面部分内容更新。
补充:pushState、replaceState 这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础上,他们提供了对当前浏览器进行修改的功能,只是当它们被修改时,虽然浏览器的URL发生
12、nextTick 作用和实现
作用:vue 更新 dom 是异步更新的,数据变化,dom 的更新不会马上完成;nextTick 的回调是在下次 DOM 更新循环结束之后执行的延迟回调。
13、solt 插槽种类以及原理
种类:
1)、匿名插槽:只能有一个
2)、实名插槽:可以有多个,在使用时必须使用name属性来标识
原理:
//子组件 <span> <slot v-bind:user="user"> {
{ user.lastName }}
slot>
span>
绑定在 元素上的 attribute 被称为插槽 prop。现在在父级作用域中,我们可以使用带值的 v-slot 来定义我们提供的插槽 prop 的名字:
//父组件 <current-user> <template v-slot:default="slotProps"> {
{ slotProps.user.firstName }}
template>
current-user>
我们选择将包含所有插槽 prop 的对象命名为 slotProps,但你也可以使用任意你喜欢的名字。
原理:
本题参考
14、keep-alive使用和原理
缓存实现过程:
15、MVVM 和 MVC
1)、MVVM 即 Model-View-ViewModel 的简写。即模型-视图-视图模型。模型(Model)指的是后端传递的数据。视图(View)指的是所看到的页面。视图模型(ViewModel)是 mvvm 模式的核心,它是连接 view 和 model 的桥梁。它有两个方向:一是将模型(Model)转化成视图(View),即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将视图(View)转化成模型(Model),即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。
2)、MVC 是 Model-View- Controller 的简写。即模型-视图-控制器。M 和 V 指的意思和 MVVM 中的 M 和 V 意思一样。C 即 Controller 指的是页面业务逻辑。使用 MVC 的目的就是将 M 和 V 的代码分离。MVC 是单向通信。也就是 View 跟 Model,必须通过 Controller 来承上启下。MVC和MVVM的区别并不是VM完全取代了C,只是在MVC的基础上增加了一层VM,只不过是弱化了C的概念,ViewModel 存在目的在于抽离 Controller 中展示的业务逻辑,而不是替代 Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用,使开发更高效,结构更清晰,增加代码的复用性。
可以参考阮一峰的文章很详细
16、template 模板引擎的渲染过程
template 的作用是模板占位符,可帮助我们包裹元素,但在循环过程当中,template不会被渲染到页面上
17、SPA页面的理解
SPA (single-page application:单页面应用程序)在页面初始化的时候加载相应的 HTML、js、css,一旦加载完成,页面不会因为用户的操作进行页面的重新加载或者跳转,而是使用路由机制实现HTML内容转换,避免页面重新加载。
优点:
缺点:
18、vue 性能优化?
npm install --save-dev compression-webpack-plugin@1.1.11
在nginx.conf 里面配置
http { //在 http中配置如下代码, gzip on; gzip_disable "msie6"; gzip_vary on; gzip_proxied any; gzip_comp_level 8; #压缩级别 gzip_buffers 16 8k; #gzip_http_version 1.1; gzip_min_length 100; #不压缩临界值 gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png; }
<body> <div id="app">
div> <script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js">
script> <script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js">
script> <script src="https://cdn.bootcss.com/vue-router/3.0.4/vue-router.min.js">
script>
body>
在 vue.config.js(vue-cli3) 文件 ,build/webpack.base.conf.js(vue-cli2)文件,增加 externals,将引入的外部模块导入
module.exports = { entry: { app: './src/main.js' }, externals:{ 'vue': 'Vue', 'vue-router': 'VueRouter', 'vuex':'Vuex' }
最后、去掉 inport 以及 Vue.use(xxx)
//import Vue from 'vue' //import Router from 'vue-router' //import Vuex from 'vuex' //Vue.use(Router) ///Vue.use(Vuex)
好处:加快打包速度,减轻服务器访问压力。
7)、代码精简,去除 console ,可复用的方法、组件提取出来
8)、不要写行内样式,避免dom重绘
10)、SPA页面采用keep-alive缓存组件
11)、key保证唯一性
12)、v-if 当值为false时内部指令不会执行,具有阻断功能,很多情况下使用v-if替代v-show
13、服务端渲染ssr
19、父子组件加载顺序
20、Vue.use是做什么的,原理是什么
21、Proxy 与 Object.defineProperty 优劣对比
22、v-model 的原理
v-model本质就是一个语法糖,可以看成是value + input方法的语法糖,是 vue 的双向绑定指令。一方面 model 层通过 defineProperty 来劫持每个属性,一旦监听到变化通过相关的页面元素更新。另一方面通过编译模板文件,为控件的 v-model 绑定 input 事件,从而页面输入能实时更新相关 data 属性值。
可以通过model属性的prop和event属性来进行自定义。原生的v-model,会根据标签的不同生成不同的事件和属性。
23、v-if 和 v-show 的区别
24、v-for 和 v-if 优先级
25、Vue.mixin 使用场景和原理
Vue.mixin的作用就是抽离公共的业务逻辑,原理类似“对象的继承”,在使用 mixin 的组件中引入后,mixin 中的方法和属性也就并入到该组件中,可以直接使用;当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并,如果混入的数据和本身组件中的数据冲突,会采用“就近原则”以组件的数据为准。
//全局引用 main.js import mixin from './mixin' Vue.mixin(mixin) //在vue文件中引用 import '../mixin'; // 引入mixin文件 export default { mixins: [mixin] }
同名选项合并:
26、Vue.set
起因:因为 ES5 的限制,vue 无法检测到对象属性的添加和删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
用法:Vue.set(target, key, value)
向响应式对象中添加一个属性,并确保这个新属性同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新属性,因为 Vue 无法探测普通的新增属性。(对象不可以是 Vue 实例)
执行流程:
Vue.set( ) 是将 set 函数绑定在 Vue 构造函数上,this.$set() 是将 set 函数绑定在 Vue原型上。
27、组件中写 name 选项有哪些好处
28、vue 组件通讯有哪些方法
1)、props / $emit 适用 父子组件通信(常规操作)
父组件通过 props 传值给子组件,子组件 $emit 把自己的消息发送给父组件
2)、ref 与 $parent / $children 适用 父子组件通信
3)、EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信
通过一个空的Vue实例作为中央事件总线,用它来触发事件和监听事件
4)、$ attrs/$listeners 适用于 隔代组件通信
简单来说:$ attrs与$ listeners 是两个对象,$ attrs 里存放的是父组件上绑定的非 Props 属性,$ listeners里存放的是父组件中绑定的非原生事件。
5)、provide / inject 适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
6)、Vuex 适用于 父子、隔代、兄弟组件通信
29、vue 组件的data 为什么是一个函数
组件是可复用的,一个组件被创建好之后,就可能被用在各个地方,而组件不管被复用了多少次,组件中的 data 数据都应该是相互隔离,互不影响的,基于这一理念,组件每复用一次,data 数据就应该被复制一次,之后,当某一处复用的地方组件内 data 数据被改变时,其他复用地方组件的 data 数据不受影响.
组件中的 data 写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。而单纯的写成对象形式,就使得所有组件实例共用了一份 data,就会造成一个变了全都会变的结果。(对象为引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;而使用返回对象的函数,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题)
30、data 里面数据量比较大如何优化
vue 把 data、props、store 等数据做成响应式,也就是会对这些响应式数据做深度监听,给每一个object类型的key(包括嵌套object)添加observer(vue3使用proxy)。所以如果我们不需要数据是响应式的,可以在.vue 文件头部直接使用 let、const 定义变量,在组件销毁的时候将该这些变量设为null。
31、子组件里面可以修改父组件的值吗
答案是传递的是对象和数组可以修改,如果是基础数据类型也可以修改,但是控制台会报错;对象和数组修改之后父组件是可以监听到这个值的变化的。那么为什么呢?
对象和数组都是引用类型,父组件传递过来的是一个地址,子组件修改的是地址里面的内容,地址本身并没有变,所以不会报错,但是基础数据类型就不同了,他是直接修改了传递的值,但是 vue 不允许在子组件里面直接修改prop值,所以就会报错。
32、生命周期钩子是如何实现的
Vue的生命周期钩子就是回调函数而已,当创建组件实例的过程中会调用对应的钩子方法。
内部主要是使用callHook方法来调用对应的方法。核心是一个发布订阅模式,将钩子订阅好(内部采用数组的方式存储),在对应的阶段进行发布。
33、什么是 vue-loader
作用:解析和转换.vue文件。提取出其中的逻辑代码 script,样式代码style,以及HTML 模板template,再分别把他们交给对应的loader去处理
用途:js可以写es6,style样式可以写scss或less
特性:
1、允许为 Vue 组件的每个部分使用其它的 webpack loader,例如在
34、vue 是怎么检测数组的变化的
流程:
35、vue 是怎样依赖收集的?(dep 和 Watcher 是什么关系)
注意:Dep 是一个用来负责收集 Watcher 的类,Watcher 是一个封装了渲染视图逻辑的类,用于派发更新的。Watcher 是不能直接更新视图的还需要结合 vdom 经过 patch() 中的 diff 算法才可以生成真正的 DOM
36、vue路由的钩子函数(导航守卫)
37、vue $route 和 $router 的区别
38、vue 中的 diff 算法原理
diff 算法的原理是递归加上遍历节点来比较节点复用性。diff 算法通过对比虚拟树的差异,将差异通过 patch (补丁)一边比较一边打补丁方式更新到真实 dom 节点上。patch 函数是 diff 流程的入口函数。在采取diff算法比较新旧节点的时候,比较只会在同层级进行, 不会跨层级比较。
在数据发生变化的时候,set 方法就会调用 dep.notify 通知所有订阅者,订阅者会调用 patch 给真实的 dom 打补丁,更新相应的视图。
更详细内容参考
39、Vue. extend 能做什么
作⽤是扩展组件⽣成⼀个构造器,通常会与 $mount ⼀起使⽤。
<div id="mount-point">
div>
// 创建构造器 var Profile = Vue.extend({ template: '<p>{
{firstName}} {
{lastName}} aka {
{alias}}
p>', data: function () { return { firstName: 'Walter', lastName: 'White', alias: 'Heisenberg' } } }) // 创建 Profile 实例,并挂载到一个元素上。 new Profile().$mount('#mount-point')
这样div里面就有了下面内容
<p>Walter White aka Heisenberg
p>
40、vue 的 mixin 和 mixins 区别
41、vue 组件渲染和更新的过程
渲染:
更新:
42、vue 为什么采用异步渲染
因为如果不采用异步更新,那么每次更新数据都会对当前组件进行重新渲染;所以为了性能考虑,Vue会在本轮数据更新后,再去异步更新视图。
原理:
43、vue 为什么要使用异步组件
原理:在createComponent方法中,会有相应的异步组件处理
44、vue 如何快速定位那个组件出现性能问题的
⽤ timeline ⼯具。 通过 timeline 来查看每个函数的调⽤时常,定位出哪个函数的问题,从⽽能判断哪个组件出了问题
45、vue3.x 对比 vue2.x 变化
https://blog.csdn.net/r/article/details/
46、watch 的 deep 如何实现的
watch 在监听对象的时候,如果 deep 值是 true,就会执行 traverse 这个方法,这个方法里就是做了个数组递归,如果是数组的话,会根据数组的每一项索引取值,进行递归追加依赖,如果是对象会拿 key 进行遍历取值,进行递归追加依赖,traverse 就是deep:true实现的核心。这样就会把数组或者对象的每一个属性都追加依赖进行监听,只要依赖发生变化就会通知视图更新。
47、v-html 会导致那些问题
48、v-el作用
提供一个在页面上已存在的 DOM元素作为 Vue实例的挂载目标.可以是 CSS 选择器,也可以是一个 HTMLElement 实例,
48、说说vue的动态组件
<div id="app"> <component is="one">
component>
div> new Vue({ el: '#app', components: { one: {template: '<div>我是线路一
div>'}, two: {template: '<div>我是线路二
div>'}, thr: {template: '<div>我是线路三
div>'} } })
49、怎么定义vue-router的动态路由?怎么获取传过来的值?
//index.js path:'/user/:id', compunent: user
// 方法1: <router-link :to="{ name: 'users', params: { id: 123}}">按钮
router-link> // 方法2: this.$router.push({name:'users',params:{id:123}}) // 方法3: this.$router.push('/user/' + 123)
2)、query:不需要配置路由格式,使用 router 对象的 query.id 获取。
// 方法1: <router-link :to="{ name: 'users', query: { id: 123}}">按钮
router-link> // 方法2: this.$router.push({ name: 'users', query:{ id:123}}) // 方法3: <router-link :to="{ path: '/user', query: { id:123 }}">按钮
router-link> // 方法4: this.$router.push({ path: '/user', query:{ id:123 }}) // 方法5: this.$router.push('/user?uname=' + 123)
50、自定义指令
自定义指令的生命周期,有5个事件钩子,可以设置指令在某一个事件发生时的具体行为:
钩子函数的参数 (包括 el,binding,vnode,oldVnode)
51、自定义过滤器
参考:vue 全局注册过滤器 filter
52、vue 中 extend、mixins、extends的区别
1)、extend:使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件对象。
2)、mixins:可以混入多个,当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
var vm = new Vue({ created: function () { console.log(3) }, mixins: [mixinA ,mixinB ] })
3)、extends:声明扩展另一个组件(可以是一个简单的选项对象或构造函数)无需使用 Vue.extend。这主要是为了便于扩展单文件组件。和 mixins 类似。但extends只能继承一个。
var otherComp= { ... } // 继承 otherComp var comp = { extends: otherComp, ... }
总结:
以上是我总结的 VUE 相关的知识点,还会继续更新,如有错误或者遗漏的地方欢迎指正!!!
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/228854.html原文链接:https://javaforall.net
