2021Vue面试知识点(重点知识)

总结Vue需要重点掌握的知识

  1. Vue响应式原理。
  2. Vue组件之间通信的方式。
  3. 虚拟DOM
  4. vue和react异同
  5. Vue3.0和2.0的区别
  6. diff算法
  7. Proxy代理
  8. Vuex
  9. vue-router 导航守卫
  10. vue性能优化
  11. SPA单页面渲染

Vue响应式原理

当页面数据发生变化时,会对页面进行重新渲染,这就是Vue响应式。
这个过程中 Vue做了这些步骤:

  • 数据劫持 / 数据代理 (侦测数据变化)
  • 依赖收集(收集视图依赖的数据)
  • 发布订阅模式(数据发生变化时,自动通知需要更新的视图部分,进行更新)

那么如何侦测数据变化呢?
两种方法:

  1. 使用Object.defineProperty
  2. 使用proxy
Object.defineProperty

当一个普通的Js对象传入Vue实例中作为data的选项时,Vue会先遍历此对象的所有属性(property),并使用Object.defineProperty 把这些属性全部转为 getter/setter。
这些getter/setter 对于用户是不可见的,但是在内部可以让Vue追踪一来,在属性被访问和改变时进行通知变更。getter时收集依赖,setter时将收集的依赖项触发,从而更新数据。不支持数组的监听

Proxy

Proxy 的代理是针对整个对象的,而不是对象的某个属性,因此不同于 Object.defineProperty 的必须遍历对象每个属性,Proxy 只需要做一层代理就可以监听同级结构下的所有属性变化,当然对于深层结构,递归还是需要进行的。此外Proxy支持代理数组的变化。

Vue组件通信

以下摘自

vue组件通信全面总结

vue中组件通信的八种方式
场景:

  • 父->子组件间的数据传递
  • 子->父组件间的数据传递
  • 兄弟组件间的数据传递
  • 组件深层嵌套,祖先组件与子组件间的数据传递
父->子组件间的数据传递

使用props传递数据

//父组件,传递数据
<editor :inputIndex="data" :inputName="王文健"></editor>
//子组件,接受数据,定义传递数据的类型type与默认值default
    props: {
        inputIndex: {
            type: Object, 
            default: function(){
                return {}
            }
        },
        inputName: {
            type: String,
            default: ''
        },
      }
子->父组件间的数据传递
  • 使用$emit传递数据, $on接收数据
// 父组件监听子组件定义的事件
 <editor :inputIndex="index" @editorEmit='editorEmit'></editor>
// 子组件需要返回数据时执行,并可以传递数据
this.$emit('editorEmit', data)

  • 使用$ children/$ parent
//父组件
export default {
 name: 'HelloWorld',
 components: { ComA },
 data() {
 return {
  msg: 'Welcome'
 }
 },
 
 methods: {
 changeA() {
  // 获取到子组件A
  this.$children[0].messageA = 'this is new value'
 }
 }
//子组件
export default {
 data() {
 return {
  messageA: 'this is old'
 }
 },
 computed:{
 parentVal(){
  return this.$parent.msg;
 }
 }
}

$ children 的值是数组,而$ parent是个对象

  • provide和inject

父组件中通过provide来提供变量, 然后再子组件中通过inject来注入变量。

// 父组件
import comB from '../components/test/comB.vue'
 export default {
 name: "A",
 provide: {
  for: "demo"
 },
 components:{
  comB
 }
 }
// 子组件
import comC from '../components/test/comC.vue'
 export default {
 name: "B",
 inject: ['for'],
 data() {
  return {
  demo: this.for
  }
 },
 components: {
  comC
 }
 }

孙组件也可以获取父组件的for值

  • ref/refs
// 父组件
<template>
 <component-a ref="comA"></component-a>
</template>
<script>
 export default {
 mounted () {
  const comA = this.$refs.comA;
  console.log(comA.name); // Vue.js
  comA.sayHello(); // hello
 }
 }
</script>
// 子组件
export default {
 data () {
 return {
  name: 'Vue.js'
 }
 },
 methods: {
 sayHello () {
  console.log('hello')
 }
 }
}
兄弟组件间的数据传递

1.路由传参

// router index.js 动态路由
{
   path:'/params/:Id',
   component:Params,
   name:Params
}
// 跳转路由
<router-link :to="/params/12">跳转路由</router-link>

// 在跳转后的组件中用$route.params.id去获取到这个id参数为12,但只适合传递较小的数据。
  1. BUS通信
  • 新建bus.js文件
import Vue from 'vue';  
export default new Vue(); 
  • 在需要使用的两个组件内部引入 bus.js

import Bus from '../utils/bus'

// 兄组件
 methods:{
        // 点击按钮发送Bus消息
        add(){
            // 发送 myMsg 主题 的Bus消息
            Bus.$emit('myMsg', "你好啊");
        }
    }

// 弟组件
 mounted() {
      Bus.$on('myMsg', myMsg => {  
            console.log("dome02组件收到bus消息:",myMsg);  
            this.msg = myMsg
        });  
  }
组件深层嵌套,祖先组件与子组件间的数据传递
  • provide和inject (已说明)
  • $attrs 和 $listeners
    在子组件中绑定 $attrs 和 $listeners 可以将父组件传递给子组件的值全部传递给子组件的子组件(孙组件)
//father
<template>
    <div id="father">
    <child :temp="tempdata" @tempFn="fatherFn" prop='$attrs不会传递child组件中定义的props 
       值'>
      </child>
    </div>
  </template>
  <script>
   import Child from './child'
 export default {
    component: { Child },
   data() {
     tempdata: 'i am father'
   },
   methods: {
     fatherFn: function() {
       console.log('father function!');
     }
   }
 }
 </script>
// son
<template>
   <div id="child">
     <son v-bind="$attrs" v-on="$listener"></son>
   </div>
 </template>
 <script>
 import Son from './son'
 export default {
   component: {Son},
   props: { 'prop' },
   data() {
     return {}
   },
   mounted() {
     // 结果显示为$attrs.temp,不包含prop
    console.log(this.$attrs)
     this.$emit('tempFn')
   },
   methods: {}
 }
 </script>
//grandchild
<template>
   <div id="son">
     {{ $attrs.temp }}
   </div>
 </template>
 <script>
 export default {
   prop: {},
   data() {
     return {}
   },
   mounted() {
     this.$emit('tempFn')
   },
   methods: {}
 }
 </script>

虚拟dom

虚拟dom是相对于真实dom的概念,操作dom树是一件非常麻烦的是,往往是dom标签和js逻辑同事写在js文件中,容易造成代码耦合性高,难以维护。同时浏览器渲染dom非常消耗性能,尽量减少dom操作是前端性能优化的一种方式。 虚拟dom将dom的对比层放在了js层,通过比对不同来选择渲染新的dom节点,从而提高渲染效率。 虚拟dom的原理流程概括为3点: 1. 用JavaScript模拟DOM树,并渲染这个DOM树 2. 比较新老DOM树,得到比较的差异对象 3. 把差异对象应用到渲染的DOM树。 真实的dom节点:

tu1
虚拟dom节点:
在这里插入图片描述

vue和react异同

部分摘自 [覆盖vue3.0的最全vue知识点](https://www.bilibili.com/read/cv6273712/) 同: 1. 使用 虚拟dom 2. 提供响应式和组件化的视图组件 3. 都可以使用props传递给子组件数据 4. 将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。

异:

  • react使用特殊的jsx语法.
  • 改变初始数据 react需要使用setData()

Vue3.0和2.0的区别

优势: 更快、更小、更易维护、更易于原生、让开发者更轻松;
  1. virtual DOM 完全重写,mounting & patching 提速 100%;
  2. 更多编译时 (compile-time)提醒以减少 runtime 开销;
  3. 基于 Proxy 观察者机制以满足全语言覆盖以及更好的性能;
  4. 放弃 Object.defineProperty ,使用更快的原生 Proxy;
  5. 组件实例初始化速度提高 100%;
  6. 提速一倍/内存使用降低一半;
  7. 加入了 TypeScript 以及 PWA 的支持
  8. 默认进行懒观察 ,2.x版本中会一开始给数据创建观察者,新版本中只会对 用于渲染初始可见部分的数据 进行创建观察者
  9. 默认项目目录结构也发生了变化: src文件新增views文件夹,用于区分视图组件和公共组件;移除了static文件夹,新增public文件夹,index.html移动到public文件夹中。

diff算法

数据发生变化时,vue会先根据真实的dom生成一颗虚拟dom树当虚拟dom中某个节点的数据改变时,会生成一个新的vnode,将新的vnode和旧的vnode进行对比,将旧vnode中发生变化的部分更新为新的,从而实现更新节点。

原理:

  1. 先进行同级比较,再去比较子节点
  2. 先去判断一方有子节点一方没有子节点的情况
  3. 比较都有子节点的情况
  4. 递归比较子节点

使用patch方法比较节点,是同一个节点时调用patchVnode方法,比较虚拟节点的vnode和旧的vnode是否指向同一个对象,是同一个对象时直接return ,复用旧的vnode,如果不是,则进行对比,使用updateChildren比较子节点进行更新。

Proxy监听数据代理对象

Vuex

Vuex是vue的状态管理模式,核心是store,相当于仓库,用来储存状态。 包括的模块:
State:

定义应用状态的数据结构,可以在这里设置默认的初始状态

Getter:

允许组件从store中获取数据。

Mutation:

用于更改store状态的方法(同步)
在组件中使用$store.commit(’’,params)

Action:

用于提交mutation,可以包含异步操作
在组件中使用是$store.dispath(’’)

Modules:

store的子模块,为了开发大型项目,方便状态管理而使用的

Vue-router导航守卫

路由跳转过程中的钩子函数 全局守卫: beforeEach: 用于登录验证
 router.beforeEach((to,from,next)=>{
    console.log(to); //即将要进入的目标路由对象
    console.log(from); //当前导航即将要离开的路由对象;
    next(); //调用该方法后,才能进入下一个钩子函数(afterEach)。
     //next()//直接进to 所指路由
     //next(false) //中断当前路由
     //next('route') //跳转指定路由
     //next('error') //跳转错误路由
  })
  1. 完整的导航解析流程导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

Vue性能优化

编码阶段:
  • 减少data中的数据
  • v-if和v-for不能连用
  • 使用keep-alive缓存组件
  • v-if代替v-show
  • key值保证唯一性
  • 路由懒加载,异步组件
  • 防抖和接了节流
  • 第三方模块按需导入
  • 图片懒加载
打包优化:
  • 压缩代码
  • cdn加载第三方模块
用户体验:
  • 骨架屏
  • 使用缓存
  • seo搜索优化

SPA单页面加载

优点:
  • 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
  • 对服务器压力小
  • 前后端职责分明,架构清晰
缺点:
  • 初次加载耗时多:
  • 前进后退需要使用路由管理;
  • seo难度大
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Vue.js是一种流行的JavaScript框架,用于构建交互式的用户界面和单页面应用程序。它具有许多重要的特性和知识点。 首先,Vue的核心概念包括数据驱动、组件化和响应式设计。数据驱动意味着视图是由数据驱动的,当数据发生改变时,视图会自动更新。组件化使得用户界面可以被分解成独立的组件,每个组件包含自己的数据、模板和逻辑。响应式设计可以让数据变化时自动更新DOM,而不需要手动操作。 其次,Vue的重要知识点包括指令、生命周期钩子、计算属性、事件处理、过滤器等。指令是用于扩展HTML的特殊属性,例如v-if、v-for等。生命周期钩子提供了在Vue实例生命周期不同阶段执行代码的机会。计算属性可以根据依赖的数据动态计算出一个新值。事件处理允许我们对用户的输入做出响应。过滤器可以对数据进行一些处理后再显示到视图上。 最后,Vue还有一些重要的工具和插件,如Vue Router用于构建单页面应用的路由系统,Vuex用于集中式状态管理,Vue DevTools用于调试Vue应用程序等。 综上所述,Vue重点知识包括核心概念、重要知识点和工具插件。掌握这些知识可以帮助开发者更好地理解和应用Vue.js框架,从而构建出功能强大、高效的前端应用程序。若想深入学习Vue.js,可以阅读相关的pdf文档或官方文档,这将对理解和运用Vue有很大帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值