VUE基础面试题(一)

v-if 和 v-show 区别

  1. 操作手段:
    • v-if是动态的向DOM树内添加或者删除DOM元素;
    • v-show是通过设置DOM元素的display样式属性控制显隐;
  2. 编译过程:
    • v-if切换有一个局部编译/卸载的过程,切换过程中合适当地销毁和重建内部的事件监听和子组件;
    • v-show只是简单的基于css切换;
  3. 编译条件:
    • v-if是惰性的,如果初始条件为假则什么也不做,只有在条件第一次变为真时才开始局部编译;
    • v-show是在任何条件下都被编译,然后被缓存,而且DOM元素保留;
  4. 性能消耗:
    • v-if有更高的切换消耗;
    • v-show有更高的初始渲染消耗;
  5. 适用场景:
    • v-if 适合运营条件不大可能改变的场景;
    • v-show适合频繁切换的场景。
  6. 总结:
    • v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,如果要频繁切换某节点时,故v-show性能更好一点。

vue常用的修饰符

  • .prevent: 阻止默认事件的发生,例如:提交事件不再重载页面;
  • .stop: 阻止事件进行冒泡;
  • .self: 元素绑定的事件只会在元素自身触发,而子元素无法调用;
  • .capture: 事件侦听,事件发生的时候会调用。

js中的冒泡是什么?vue中如何阻止冒泡事件

  1. js中冒泡的概念:父元素内多级子元素绑定了同一个事件,js会依次从内往外或者从外往内执行每个元素的该事件,从而引发冒泡。
  2. js阻止冒泡方法:event.stopPropagation();或者在使用 addEventListener注册事件时,将第三个参数设置为 false;
  3. vue中阻止冒泡: 事件.stop,例如:@click.stop="" 、@mouseover.stop=""

vue中常用的一些指令

  1. v-model:用于表单输入,实现表单控件和数据的双向绑定;
  2. v-on:简写为@,基础事件绑定;
  3. v-bind:简写为:,动态绑定一些元素的属性,类型可以是:字符串、对象或数组;
  4. v-if:作用与js中的if语句相似,可以在实例中定义判断语句,也可以在dom处直接定义三元运算,取值为true/false,控制元素是否需要被渲染,可以与v-else 配合使用;
  5. v-else指令:和v-if指令搭配使用,没有对应的值。当v-if的值false,v-else才会被渲染出来;
  6. v-else-if:必须和 v-if 配合使用,作用与 else-if 相似;
  7. v-show指令:指令的取值为true/false,分别对应着显示/隐藏;
  8. v-for指令:遍历data中存放的数组数据,实现列表的渲染;
  9. v-once: 通过使用 v-once 指令,你也能执行一次性地插值,当数据改变时,插值处的内容不会更新;
  10. v-pre:正文中包含了不希望被vue编译的{{ }}时,采用v-pre保护;
  11. v-html:绑定一段HTML代码片段到页面上。

vue的自定义指令

Vue除了核心功能默认内置的指令 ,Vue 也允许注册自定义指令。

自定义指令是用来操作DOM的。尽管Vue推崇数据驱动视图的理念,但并非所有情况都适合数据驱动。自定义指令就是一种有效的补充和扩展,不仅可用于定义任何的DOM操作,并且是可复用的。

添加自定义指令的两种方式:

  • 全局指令: 通过 Vue.directive() 函数注册一个全局的指令。
  • 局部指令:通过组件的 directives 属性,对该组件添加一个局部的指令。

vue的指令周期

指令调用周期
bind一次初始化调用
inserted被绑定元素插入父节点调用
update模板更新时调用
unbind指令与元素解绑时调用
vue.nextTick在dom更新后执行,一般用于dom操作
vue.$nextTick一直到真实的dom渲染结束后再执行

vue循环中 key值的作用

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,默认用“就地复用”策略,如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。

v-for循环遍历时为什么要加上 “:key”?

  1. 为每个元素添加唯一标识;
  2. 避免重建整个列表;
  3. 提高修改效率。

为什么避免 v-if 和 v-for 一起使用?

当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,通过v-if 移动到容器元素,不会再重复遍历列表中的每个值。取而代之的是,我们只检查它一次,且不会在 v-if 为否的时候运算 v-for。

Vue的生命周期

  • 什么是生命周期:
    • Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom 渲染 更新 渲染 卸载等一系列过程,我们称这是 Vue 的生命周期。
  • 生命周期各阶段的作用:
    • beforeCreate(创建前)数据观测和初始化事件还未开始;
    • created(创建后)完成数据观测,属性和方法的运算,初始化事件,$el属性还未显示出来;
    • beforeMount(挂载前)在挂载开始之前被调用,相关的render函数首次被调用,实例已完成以下的配置:编译模板,把data里面的数据和模板生成html;注意此时还没有挂载html到页面上;
    • mounted(挂载后)el被新创建的 vm.$el 替换,并挂载到实例上去调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互;
    • beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程;
    • updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用;
    • beforeDestroy(销毁前) 在实例销毁之前调用,实例仍然完全可用;
    • destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
      点击查看详解

Vue组件间参数的传递

  • 父子组件间传参

    • 父给子传参(父:自定义属性传递变量;子:用Props[‘父元素自定义属性’]接受)
    • 给父传参(子:this.$emit(父元素自定义事件,传递的值) ;父:自定义事件用参数去接收传递来 的值)
  • 兄弟间传参(除了以下方式也可直接用Vuex)

    • 通过给eventbus注册事件,别的组件触发事件,实现通信。
      1. 创建一个eventbus对象,即创造一个vue对象,用作传递信息。
      2. 接收信息的一方将事件通过vm.$on(“事件名”,事件处理函数)添加在eventbus对象上。
      3. 发送数据的一方,通过vm.$emit(“事件名”,传递的数据)触发事件,将数据传递。
  • 路由传参

    • 通过params
    //需要在router的path后跟上参数
    {
       path: "/two",
       name: "two",
       component: two
    }
     
    //跳转时
       this.$router.push({
          path: `/two` //直接把数据拼接在path后面
       })
     
    //接收时
       this.$route.params
    
    • 通过query
    //跳转时
    this.$router.push({
        path: `/two`,
        query: { id: this.message, data: 456 }
    });    
     
    //接收时            
        this.$route.query
    
  • params 和 query 都是传递参数的,params不会在url上面出现,并且params参数是路由的一部分,是一定要存在的 , query是我们通常看到的url后面的跟在 “?”后面的拼接显示的携带参数。

Vue的父组件和子组件生命周期钩子函数执行顺序

Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分:

  1. 加载渲染过程:

    父 beforeCreate --> 父 created --> 父 beforeMount --> 子 beforeCreate --> 子 created --> 子 beforeMount --> 子 mounted --> 父 mounted

  2. 子组件更新过程:

    父 beforeUpdate --> 子 beforeUpdate --> 子 updated --> 父 updated

  3. 父组件更新过程:

    父 beforeUpdate --> 父 updated

  4. 销毁过程:

    父 beforeDestroy --> 子 beforeDestroy --> 子 destroyed --> 父 destroyed

methods、computed、watch的区别

  1. methods是个方法,执行的时候需要事件进行触发;
  2. computed是一个计算属性,是实时响应的,只要data中的属性发生了变化那么就会触发computed,计算属性是基于属性的依赖进行缓存的,methods调用的时候需要加(),而computed调用的时候不需要加();
  3. watch用来监听属性的变化,当值发生变化的时候来执行特定的函数,watch监听属性的时候会有2个参数newVal和oldVal一个新值一个旧值。

可以在哪个生命周期内调用异步请求?

可以在钩子函数 created(创建后)、beforeMount(挂载前)、mounted(挂载后) 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。但是更推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:

  1. 能更快获取到服务端数据,减少页面 loading 时间;
  2. ssr 不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性。

在vue生命周期的什么阶段才能访问操作DOM

在钩子函数 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。

vue项目性能优化

  1. 编码层优化:
    • 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
    • v-if 和 v-show 区分使用场景
    • v-for 遍历必须为 item 添加 key,且保证key值唯一
    • 避免连用 v-for 和 v-if
    • computed 和 watch 区分使用场景
    • 使用路由懒加载、异步组件
    • 第三方模块,插件按需导入
    • 如果需要使用v-for给每项元素绑定事件时,使用事件代理(事件委派)
    • 优化无限列表性能,长列表滚动到可视区域动态加载
    • 图片资源懒加载
    • SPA 页面采用keep-alive缓存组件
    • 适当进行事件销毁
    • 设置防抖,节流
    • 服务端渲染 SSR or 预渲染
  2. 打包优化:
    • Webpack 对图片进行压缩
    • 减少 ES6 转为 ES5 的冗余代码
    • 模板预编译
    • 提取公共代码
    • 提取组件的 CSS
    • 使用cdn加载第三方模块
    • 多线程打包happypack
    • splitChunks抽离公共文件
    • sourceMap优化
    • Vue 项目的编译优化
    • 构建结果输出分析
  3. 基础的 web 技术的优化
    • 开启 gzip 压缩
    • 使用浏览器缓存
    • 使用CDN
    • 使用 Chrome Performance 查找性能瓶颈

虚拟DOM的优缺点

  1. 优点:
    • 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
    • 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
    • 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。
  2. 缺点:
    • 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

虚拟DOM的实现原理

虚拟 DOM 的实现原理主要包括以下 3 部分:

  1. 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
  2. diff 算法 — 比较两棵虚拟 DOM 树的差异;
  3. pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。

直接给一个数组项赋值,Vue 能检测到变化吗?

由于 JavaScript 的限制,Vue 不能检测到以下数组的变动:

  1. 利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  2. 当你修改数组的长度时,例如:vm.items.length = newLength

为了解决第一个问题,Vue 提供了以下操作方法:


// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
 
// vm.$set,Vue.set的一个别名
vm.$set(vm.items, indexOfItem, newValue)
 
// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)

为了解决第二个问题,Vue 提供了以下操作方法:

// Array.prototype.splice
vm.items.splice(newLength)

vuex有哪几种属性?

有五种,分别是 State、Getter、Mutation 、Action、Module;

  1. state为单一状态树,在state中需要定义我们所需要管理的数组、对象、字符串等等,只有在这里定义了,在vue.js的组件中才能获取定义对象的状态;
  2. getter类似vue.js的计算属性,当我们需要从store的state中派生出一些状态时,就需要使用getter,getter会接收state作为第一个参数,而且getter的返回值会根据它的依赖被缓存起来,只有getter中的依赖值(state中的某个需要派生状态的值)发生改变的时候才会被重新计算;
  3. 更改store中state状态的唯一方法就是提交mutation,每个mutation都有一个字符串类型的事件类型和一个回调函数,我们需要改变state的值就要在回调函数中改变,要执行这个回调函数,就需要执行一个相应的调用方法:store.commit;
  4. action可以提交mutation,在action中可以执行store.commit,而且action中可以有任何的异步操作。在页面中如果我们要用这个action,就需要执行store.dispatch;
  5. 当state中很复杂臃肿的时候,module可以将store分割成模块,每个模块中拥有自己的state、mutation、action和getter。

不使用vuex会带来什么问题?

  1. 可维护性会下降,要想修改数据,得维护三个地方;
  2. 可读性会下降,因为一个组件里的数据,看不出来是从哪来;
  3. 增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。

简述vuex的数据传递流程

当组件进行数据修改的时候我们需要调用dispatch来触发actions里面的方法,actions里面的每个方法中都会 有一个commit方法,当方法执行的时候会通过commit来触发mutations里面的方法进行数据的修改,mutations里面的每个函数都会有一个state参数,这样就可以在mutations里面进行state的数据修改 ,当数据修改完毕后,会传导给页面,页面的数据也会发生改变。

解释一下vuex

vuex是用来做状态管理的,有五个常用属性state, getter, actions, mutations, modules;

  1. state是数据源,类似vue中的data,我们可以通过两种方式来获取它,mapStates, mapGerters。获取state必须放到computed中,这样才能保证state发生改变的时候该组件中用到state的地方都发生变化
  2. getters:相当于计算属性;
  3. mutation:同步操作, 修改数据;
  4. action:异步操作;
  5. modules:模块化

如何获取vuex的state对象中的属性?

方法1:直接从store实例中取值 ****this.$store.state.属性****;

方法2:利用vuex的mapState方法来获取vuex的state对象中属性;


import { mapState } from 'vuex'
 
//在computed中
        computed:{
            ...mapState({
                count:state => state.count   //使用ES6的箭头函数来给count赋值
            })
 
        }
//在computed中也可写成数组格式
        computed:
            ...mapState(['count'])
        }

使用vue脚手架搭建的项目中怎样使用自定义组件?组件使用时注意什么?

  1. 第一步:在components目录新建组件文件(smithButton.vue),在组件文件中的script代码中一定要用 export default 将组件导出;
  2. 第二步:在需要用的页面(组件)中导入:import smithButton from ‘…/components/smithButton.vue’;
  3. 第三步:注入到vue的子组件的components属性上面,components:{smithButton};
  4. 第四步:在template视图view中使用,
  5. 注意:可以使用 smithButton命名组件,但是使用的时候应该是:smith-button的形式(浏览器识别HTML标签是不区分大小写)。

这里是万物之恋,我们下次再见了!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值