vue的面试题深层次

vue的面试题深层次

文章目录


一、在vue中watch和created哪个先执行?为什么?

如果watch 加了 immediate: true, 就是watch先执行,否则就是created 先执行
1、正常的顺序执行
create=》beforeMount=》computed=》mounted=》watch

  • created执行时挂载阶段还没有开始,模版还没有渲染成html,所以无法获取元素。created钩子函数主要用来初始化数据。
  • beforeMount 这一步的时候,模版已经在内存中编译好了,但是尚未挂载到页面中去。
  • computed是在DOM执行完成后立马执行(如:赋值)
  • mounted钩子函数一般用来向后端发起请求,拿到数据后做一些业务处理。该函数在模版渲染完成后才被调用。DOM操作一般是在mounted钩子函数中进行。
  • watch用于检测vue实例上数据的变动
  • 默认加载的时候先computed再watch,不执行methods;等触发某一事件后,则是:先methods再watch。methods方法有一定的触发条件,如click等。所有方法都应该在methods里定义,在mounted或created里面使用this调用,用这种方法实现初始化。

2、设置了watch immediate:true 他的优先级会提到最前面
watch:immediate=》create=》beforeMount=》computed=》mounted=》watch
3、设置了watch immediate:true,监听的是计算属性的值 他的优先级应该会提到最前面,但是vue默认先computed 再执行watch
computed:(watch监听的)=》watch:immediate=》create=》beforeMount=》computed=》mounted=》watch

二 、vue中mixins和extends有什么区别?

mixins

mixins: 选项接收一个混入对象的数组。这些混入对象可以像正常的实例对象一样包含实例选项,这些选项将会被合并到最终的选项中,使用的是和Vue.extend() 一样的选项合并逻辑。
mixins的几个规则:

  • 一、触发生命周期钩子函数时,先触发mixins组件中的钩子,再调用组件自身的函数。
  • 二、当mixins数组中有watch,混入的组件中也存在watch,而且watch中的key相同时,混入组件中的watch会先触发,而后再是组件中的watch触发
  • 三、data、methods内函数、components和directives等键值对格式的对象均以组件自身或实例为准,组件自身没有定义才会去mixins混入的组件中去找。
  • 四、watch,mixins数组中的组件和组件自身的watch会合并在一个数据中,mixins中的组件中的watch会先运行,而后再是组件自己的watch
  • 五、mixins选项合并:当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”。数据对象在内部会进行递归合并,在有同名的keys时以组件数据优先。

extends

extends允许声明扩展另一个组件 (可以是一个简单的选项对象或构造函数),而无需使用 Vue.extend。这主要是为了便于扩展单文件组件。这和 mixins 类似。

区别:

  • 1、mixins接收对象数组(可理解为多继承),extends接收的是对象或函数(可理解为单继承)
  • 2、优先级>extends>mixins,继承钩子函数的时候,是不进行覆盖的,extends的钩子函数先触发,而后再是mixins的钩子函数触发,最后就是组件自身的钩子函数触发。
  • 3、mixins类似于面向切面的编程(AOP),extends类似于面向对象的编程

使用场景:

当存在多个组件中的数据或者功能很相近时,就可以利用mixins将公共部分提取出来,通过 mixins封装的函数,组件调用他们是不会改变函数作用域外部的。

mixins和vuex的区别:

  • vuex公共状态管理,在一个组件被引入后,如果该组件改变了vuex里面的数据状态,其他引入vuex数据的组件也会对应修改,所有的vue组件应用的都z是同一份vuex数据。(在js中,有点类似于浅拷贝)
  • vue引入mixins数据,mixins数据或方法,在每一个组件中都是独立的,互不干扰的,都属于vue组件自身。(在js中,有点类似于深度拷贝)

mixins和组件的区别:

  • 组件:在父组件中引入组件,相当于在父组件中给出一片独立的空间供子组件使用,然后根据props来传值,但本质上两者是相对独立的。
  • Mixins:则是在引入组件之后与组件中的对象和方法进行合并,相当于扩展了父组件的对象与方法,可以理解为形成了一个新的组件。
    (装饰器模式)

三、created()和activated()的区别

  • created():在创建vue对象时,当html渲染之前就触发;但是注意,全局vue.js不强制刷新或者重启时只创建一次,也就是说,created()只会触发一次;
  • activated():在vue对象存活的情况下,进入当前存在activated()函数的页面时,一进入页面就触发;可用于初始化页面数据等

四、在vue项目如何引入异步组件?

在项目执行的时候不加载,在需要的时候才加载。比如说弹框啦。const List = () => import(“./list”)一句话就是箭头函数

五、在vue项目中scss scoped穿透符>>>无效的解决方案有哪些?

<style lang="scss" scoped>
.a >>> .b {//上述代码将会编译成:.a[data-v-f3f3eg9] .b { /* ... */ }
</style>

修改为:

<style lang="scss" scoped>
.a /deep/ .b {
  font-size: 24px;
}
</style>

六、v-if和v-for的那个优先级更高,如果两个同时出现,应该怎么优化得到更好的性能

结论: v-for优先于v-if被解析
查看vue源码:路径为src/compiler/codegen/index.js文件中发现
 v-for优先于v-if被解析
在源码中发现 先处理静态节点(staticRoot) 然后处理once 最后才会处理for 代码显示for优先于if 断点调试之后也是证实for优先于if
结论:

  • v-for优先于v-if被解析就从源码来说也是先执行的for
  • 如果同时出现,每次渲染都会先执行循环在判断条件,无论如何循环都不可避免,浪费了性能
  • 要避免出现这种情况,在外层嵌套template,在这一层进行v-if判断,然后在内部进行v-for循环或者使用计算属性代替

七、v-for 绑定key值,不建议使用index (原因详解)

使用v-for更新已渲染的元素列表时,默认用就地复用策略;列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;
我们在使用的使用经常会使用index(即数组的下标)来作为key,但其实这是不推荐的一种使用方法;
比如使用索引作为了key值,那么我重新插入一条数据,那么另外的三条数据都重新渲染了。此时就用到了diff算法

源码中找答案:src/core/vdom/patch.js-updateChildren()
可以唯一确定一个dom元素,从而执行diff算法更高效
案例分析:执行2秒后在c的前面插入f

key工作原理,说说对它的理解
key工作原理,说说对它的理解
key工作原理,说说对它的理解
如果不使用key 更新了3次 一次插入操作
使用了key只做了一次插入操作

  • 1、key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准的判断两个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少了dom的操作量,提高性能
  • 2、如果不设置key可能在列表更新时引发一些隐藏的bug 比如说更新和不更新看不出来。
  • 3、vue中在使用相同标签名元素的过渡切换是,也会用到key属性,其目的也是为了让vue可以区分他们,否则vue只会替换其内部属性而不会触发过渡效果。需要用key来作为唯一性的判断。

八、怎么理解vue中的diff算法

怎么理解vue中的diff算法

  • diff算法:并非vue中专用,凡是涉及到虚拟dom中都有diff算法
  • 必要性:diff算法能精确的比较新旧虚拟DOM中的key的变化,从而提高更新效率
  • 执行方式:深度优先,同级比较

1、diff算法必要性:lifecycle.jsdiff算法必要性:
结论:组件中存在多个data中key的使用,怎么确保key发生了变化,执行diff算法就可以比较新旧两次虚拟dom的比较,为了精确的知道
2、diff算法的执行方式patch.js核心源码:586行开始
diff算法的执行方式patch.js
分析:patchVnode是diff发生的地方,整体策略:深度优先,同层比较,先开始比较根节点,看看是否有子节点,如果都有,更新子节点 在比较子节点,直到底层。具体代码
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、diff算法的高效性:
就是上面提到的updateChildern()
总结:
1、diff算法是虚拟DOM技术的必然产物:通过新旧虚拟DOM做对比(既diff),将变化的地方更新在真实DOM上,另外,也需要diff高效的执行对比过程,从而降低时间复杂度为O(n)
2、vue2.0x中为了降低watcher粒度,每个组件只有一个watcher与之对应,只有引入diff才能精确的找到发生变化的地方
3、vue中diff执行的时刻是组件实例执行更新函数时,它会对比与上一次渲染结果oldVnode和新的渲染结果,此过程称为patch
4、diff过程整体遵循深度优先,同层次比较的策略,两个节点之间比较会根据他们是否拥有子节点或者文本节点做不同操作,比较两组子节点是算法重点,首先假设头部节点可能相同做4次对比尝试,如果没有找到相同节点才按照通用的方式去进行遍历查找,查找结束再按情况处理剩下的节点,借助key通常可以非常精确找到相同节点,因此整个patch过程非常高效。

九、vue-loader在webpack编译流程中的哪个阶段?

编译模板阶段:从入口文件出发,调用所有配置的Loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理

十、预渲染和SSR(服务端渲染)有什么区别?

服务端渲染和预渲染的使用场景还是有较明显的区别的。预渲染的使用场景更多是我们所说的静态页面的形式。服务端渲染适用于大型的、页面数据处理较多且较为复杂的、与服务端有数据交互的功能型网站,一个明显的使用场景就是电商网站。
相同点: 预渲染与服务端渲染的共同点: 都是多页面, 根据客户端的url 返回响应的文件。
不同点: 预渲染html文件的生成 在客户端 , 服务端则反之。
服务端渲染SSR是这样执行的. 当服务器收到客户端的请求时,会在服务端直接把文件执行完,生成最终的html文件,在发给客户端。 既然是服务端直接执行,那么收到的客户端参数也就可以放在文件中执行了。服务端渲染的过程为:服务器端执行JS => 构建HTML页面(将HTML的符号(比如{{}})用数据填充) => 输出HTML给浏览器。
预渲染: 在构建时为了特定的路由生成特定的几个静态页面,等于我们可以通过 Webpack 插件将一些特定页面组件 build 时就编译为 html 文件,直接以静态资源的形式输出给搜索引擎。

十一、你有用过预渲染技术吗?怎么做的?

https://blog.youkuaiyun.com/huangjianfeng21/article/details/92421738

十二、vue的.sync修饰符可以用表达式吗?为什么?

  • 带有.sync的修饰符,是不可以和表达式一起使用的,取而代之的是,只能提供你想要绑定的属性名,类似v-model
  • 把v-bind.sync用在一个字面量的对象上,例如: v-bind.sync="title:doc.title"是无法正常工作的,因为解析这样复杂表达式的时候,有很多边缘需要考虑

十三、Vue中v-if和v-show的区别

* 手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样式属性控制显隐;
* 编译过程:v-if切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件;v-show只是简单的基于css切换;
* 编译条件:v-if是惰性的,如果初始条件为假,则什么也不做;只有在条件第一次变为真时才开始局部编译; v-show**加粗样式**是在任何条件下,无论首次条件是否为真,都被编译,然后被缓存,而且DOM元素保留;
* 性能消耗:v-if有更高的切换消耗;v-show有更高的初始渲染消耗;
* 使用场景:v-if适合运营条件不大可能改变;v-show适合频繁切换
* 

十四、v-if和v-show哪个优先级更高?v-show指令算是重排吗?

页面渲染时,当页面中元素的位置,大小或结构、定位发生改变,或者对HTML结构增删查改时,浏览器会对所有的dom进行重新排序,这就是DOM回流,严重影响浏览器性能。
v-show指令其原理就是改变display涉及到了DOM结构所以发生了重排。

十五、axios同时请求多个接口,如果当token过期时,怎么取消后面的请求?

使用的 Axios 做数据请求,使用 cancel token 取消请求

import axios from 'axios'
    let cancel
    let CancelToken
    
    mounted() {
        CancelToken = axios.CancelToken
    }
    
    // 多次触发fetchList请求 取消上次请求,触发最新请求
    async fetchList() {
        if(cancel) {
            cancel()
        }
        await axios.post('/user/list', {
            query: ''
        }, {
            cancelToken: new CancelToken(function executor(c) {
                cancel = c
            })
        })
    }

十六、你知道v-model的原理吗?说说看

原生input其实只是一个语法糖,:bind="value"与@change="value = $event.target.value"的结合。自定义组件的时候的v-model默认监听change事件和绑定value 的prop。

<input v-model="searchText">
实际上相当于:
<input v-bind:value="searchText" v-on:input="searchText = $event.target.value" >

十七、你有使用过vue开发多语言项目吗?说说你的做法?

1、npm install vue-i18n
2、在 main.js 中引入 vue-i18n (前提是要先引入 vue)
3、准备本地的翻译信息
4、创建带有选项的 VueI18n 实例
4、把 i18n 挂载到 vue 根实例上	

十八、在使用计算属性的时,函数名和data数据源中的数据可以同名吗?

不能同名 因为不管是计算属性还是data还是props 都会被挂载在vm实例上,因此 这三个都不能同名。同名说明你命名不规范
因为Props、methods、data、computed、watch都是在initState函数中被初始化的。初始化顺序就是我上面给出的顺序,本质上这些都是要挂载到this上面的,你如果重名的话,后面出现的属性自然而然会覆盖之前挂载的属性了。如果你的eslint配置比较严格的话,同名是编译不通过的。

十八、怎么解决vue动态设置img的src不生效的问题?

原因分析在VUE项目中有时会遇到需要动态修改Img的src的情况,如果直接修改会使得图片无法显示出来。这是由于src被当做静态资源处理了,并没有进行编译。
解决办法:
第一种 使用require引入图片
第二种 将图片先引入文件中
第三种 将图片放入vue项目的public文件夹中,在根目录调用

十九、vue中怎么重置data?

Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象
this. d a t a 获取当前状态下的 d a t a t h i s . data获取当前状态下的data this. data获取当前状态下的datathis.options.data()获取该组件初始状态下的data。
Object.assign(this. d a t a , t h i s . data, this. data,this.options.data())

十九、Vue.observable你有了解过吗?说说看

Vue.observable,让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象
返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器

二十、你知道style加scoped属性的用途和原理吗?

scoped 用途 scoped 是 style 标签的一个属性,当在 style 标签中定义了 scoped 时,style 标签中的所有属性就只作用于当前组件的样式,实现组件样式私有化,从而也就不会造成样式全局污染
scoped 原理 Vue 中的 scoped 属性的效果主要通过 PostCSS(一种对css编译的工具) 转译实现; 为每一个组件实例生成一个唯一的标识(相当于 HTML 中的 id 选择器的作用),一般格式为:data-v-xxxxx,即 原选择器[data-v-xxxxx]

二十一、请说下封装 vue 组件的过程?

  1. 建立组件的模板,先把架子搭起来,写写样式,考虑好组件的基本逻辑。(os:思考1小时,码码10分钟,程序猿的准则。)
  2. 准备好组件的数据输入。即分析好逻辑,定好 props 里面的数据、类型。
  3. 准备好组件的数据输出。即根据组件逻辑,做好要暴露出来的方法。
  4. 封装完毕了,直接调用即可

二十二、vue初始化页面闪动问题?

使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是我们还是有必要让解决这个问题的。
首先:在css里加上[v-cloak] {
display: none;
}。
如果没有彻底解决问题,则在根元素加上style=“display: none;” :style=“{display: ‘block’}”

二十三、在vue项目中如果methods的方法或者watch的属性用箭头函数定义结果会怎么样?

因为箭头函数默绑定父级作用域的上下文,所以不会绑定vue实例,所以 this 是undefind
源码

if (this.user) { 
        // 如果当前watcher是开发者定义的,即通过watch选项或$watch创建的watcher的cb是开发者编写的
        // 则行为不可预知,所以执行cb回调时try...catch一下,发生错误能给开发者一个友好的提示
        try { // 开发者编写的回调接收到被观察目标的新值和旧值
          this.cb.call(this.vm, value, oldValue)
        } catch (e) {
          handleError(e, this.vm, `callback for watcher "${this.expression}"`)
        }
      } else { // 不是用户创建的watcher,即渲染函数的watcher或计算属性的watcher
        this.cb.call(this.vm, value, oldValue) // 直接执行回调
      }
      配置的函数中的this指向了vm实例

二十四、你有使用过babel-polyfill模块吗?主要是用来做什么的?

举例来说,ES6在Array对象上新增了Array.from方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用babel-polyfill,为当前环境提供一个垫片。

二十五、说说你对vue的错误处理

1:errorHandler、

Vue.config.errorHandler = function(err, vm, info) {};

err指代 error 对象,info是一个 Vue 特有的字符串,vm指代 Vue 应用本身。

Vue.config.errorHandler = function(err, vm, info) {
    console.log(`Error: ${err.toString()}\nInfo: ${info}`);
};

2warnHandler用来捕获 Vue warning。记住在生产环境是不起作用的。

二十六、在vue事件中传入$event,使用e.target和e.currentTarget有什么区别?

event.currentTarget指向事件所绑定的元素,而event.target始终指向事件发生时的元素

二十七、vue怎么实现强制刷新组件?

1.如果要在组件内部中进行强制刷新:调用this.$forceUpdate()强制重新渲染组件
2.如果是刷新某个子组件:利用v-if指令的特性;当组件的key 值变更时,会自动的重新渲染

二十八、vue为什么要求组件模板只能有一个根元素?

组件的template最终会转换成VNode对象,一个组件对应一个根元素对应一个VNode对象
vue只有一个根标签的原因:
1、从查找和遍历DOM的角度来说,如果有多个根,那么查找和遍历DOM的效率会很低;
2、从Vue本身来说,如果说一个组件有多个入口多个根,那就意味着用户的组件还可以进一步拆分成多个组件,进一步组件化,会降低代码之间的耦合程度。

二十九、你有使用做过vue与原生app交互吗?说说vue与ap交互的方法

app定义一个方法传给我们,根据方法调用

三十、vue在开发过程中要同时跟N个不同的后端人员联调接口(请求的url不一样)时你该怎么办?

webpack 的devServer配置下代理多写几个代理

三十一、vue要做权限管理该怎么做?如果控制到按钮级别的权限怎么做?

<template>
  <!-- Admin can see this -->
  <el-tag v-permission="['admin']">admin</el-tag>
  <!-- Editor can see this -->
  <el-tag v-permission="['editor']">editor</el-tag>
  <!-- Editor can see this -->
  <el-tag v-permission="['admin','editor']">Both admin or editor can see this</el-tag>
</template>
<script>
// 当然你也可以为了方便使用,将它注册到全局
import permission from '@/directive/permission/index.js' // 权限判断指令
export default{
  directives: { permission }
}
</script>

三十二、vuex原理

vuex原理

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT温故而知新

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值