面试知识点回顾篇之Vue

190 阅读6分钟

前言

文章只做知识点总结!

vue底层实现原理

vue是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发相应的监听回调

  • observer(数据监听器):observer的核心是通过object.defineProperty()来监听数据的变动,内部定义setter和getter,当数据发生变化时,就会触发setter,去通知订阅者watcher
  • watcher(订阅者):watcher订阅者作为observer和compile之间通信的桥梁,主要做的事情是: 在自身实例化时往属性订阅器dep里面添加自己 自身必须有一个update方法 属性变动时,调用自身的update方法,并触发compile中绑定的回调
  • compile:主要是解析模板指令,将模板中变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加鉴定数据的订阅者,一旦数据有变动,收到通知,更新视图。

父子组件生命周期顺序

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

computed与watch区别

计算属性computed

  • 支持缓存,只有依赖更新发生改变,才会重新计算,否则从缓存中读取数据返回。
  • 函数必须用return返回
  • 默认第一次加载时候就监听
  • 一个属性受多个属性影响 侦听属性watch
  • 不支持缓存,数据改变,直接触发相应的操作。
  • watch不需要return返回
  • 默认第一次加载不监听,需要的话可以添加immedidate属性为true
  • 一条数据影响多条数据

vue常用指令

  • v-text:用于更新标签包含的文本
  • v-html:绑定html代码的数据在视图上
  • v-show:显示/隐藏
  • v-if:控制元素是否需要被渲染
  • v-else
  • v-for
  • v-bind
  • v-on
  • v-model
  • v-once:只渲染一次,后面元素中的数据再更新变化,都不会重新渲染

组件通信方式

  • 父子组件通信props/$emit
父传子:利用属性绑定(v-bind:)传递,子组件使用props接收
子传父:利用事件绑定(v-on@)传递,子组件$emit触发

兄弟组件通信emit/emit/on

Event Bus实现跨组件通信
Vue.prototype.$bus = new Vue() // 自定义事件

跨级组件通信vuex vuex、attrs/attrs/listeners、provice/inject、parent/parent/children

vuex中mutation与action的区别

  • mutation:必须是同步执行,专注于修改state。
  • action:可以异步执行,不能直接操作state,专注于业务代码,异步请求。

描述一下vuex

  • vuex主要应用于vue.js中管理数据状态的一个库。
  • 优势在于可以全局共享数据,方便统一管理。
  • 劣势在于页面刷新后state变量会还原清空

路由的两种模式

前端路由有两种模式:hash模式和history模式

  • hash模式 hash模式是一种吧路由路径用#拼接在URL后面的模式。当#号后面路径发生变化时,浏览器并不会重新发起请求,而是会触发hashchange事件。 优点:浏览器兼容性较好,IE8也支持 缺点:路径在#号后不美观
  • history模式 history是H5提供的新特性,允许开发者直接更改前端路由,即更新URL地址而不重新发起请求。
history.replaceState({}, null, '/b') // 替换路由 
history.pushState({}, null, '/a') // 路由压栈 
history.back() // 返回 
history.forward() // 前进 
history.go(-2) // 后退2次

优点:路径规范,没有#号 缺点:兼容性不如hash,且需要服务端支持,否则一刷新页面就404

devDependencies和dependencies区别

  • devDependencies下的依赖包,只在本地或开发坏境下运行代码所依赖的(比如各种loader,babel全家桶及各种webpack的插件等)只用于开发环境,不用于生产环境,因此不需要打包。
  • dependencies下的依赖包,是在线上(生产坏境)下所要依赖的包,比如vue,在线上时必须要使用的,dependencies依赖的包不仅开发环境能使用,生产环境也能使用。

css-loader和style-loader关系

vue生命周期理解

beforeCreate(创建前)

  • 在实例初始化后,数据观测和事件配置前调用
  • el及data未初始化,无法访问methods,data,computed等
  • 使用场景:设置非响应式数据

created(创建后)

  • 实例完成创建后,已完成数据观测,属性和方法的运算,watch/event事件回调,data数据初始化。
  • el未初始化
  • 使用场景:页面数据请求,初始化数据处理

beforeMount

  • dom挂载前,完成编译模板,生成html
  • dom未挂载到页面上
  • 使用场景:初始化数据处理

mounted

  • dom挂载完成,完成html渲染
  • 使用场景:页面数据请求

beforeUpdated

  • 数据更新前,虚拟dom重新渲染和打补丁前
  • 使用场景:进一步更新状态

updated

  • 数据更新且dom更新后
  • 使用场景:dom更新依赖某个状态

beforeDestroy

  • 实例销毁前调用
  • 使用场景:清除定时器,清除监听dom事件

destroyed

  • 实例销毁后调用,所有的子实例也会被销毁

插槽

具名插槽

base-layout组件

<div class="container"> 
    <header>
        <slot name="header"></slot>
    </header> 
    <main>
        <slot></slot>
    </main> 
    <footer>
        <slot name="footer"></slot>
    </footer> 
</div>
<base-layout> 
    <template v-slot:header> 
        <h1>Here might be a page title</h1> 
    </template> 
    <p>A paragraph for the main content.</p> 
    <p>And another one.</p> 
    <template v-slot:footer> 
        <p>Here's some contact info</p> 
    </template> 
</base-layout>

v-slot只能添加到template上

作用域插槽

概念:在父组件中使用子组件中的data数据

<div class="container"> 
    <header>
        <slot v-bind:userInfo="userInfos" name="headerName"></slot>
    </header> 
</div>
<base-layout v-slot:headerName="cHeaderNamer> 
   {{cHeaderNamer.userInfo}}
</base-layout>

keep-alive

概念:keep-alive是vue的内置组件,缓存不活动的动态组件实例。 作用:实现组件缓存,保持这些组件的状态,避免反复渲染导致性能问题。 应用场景:标签页使用v-if,但是使用keep-alive能缓存tab的操作状态

<keep-alive> 
    <component v-bind:is="currentTabComponent"></component> 
</keep-alive>

动态组件和异步组件

动态组件

<component v-bind:is="currentTabComponent">

异步组件

components: { 
    'my-component': () => import('./my-async-component') 
}

为什么不建议v-for和v-if一起使用

  • 当v-for和v-if在同一节点时,v-for的优先级较高,即v-if会重复运行在v-for循环中,造成性能浪费。
  • 当存在v-for和v-if共存时,建议使用computed对数据进行过滤。

key的作用

key的作用是为了在diff算法执行时更快的找到对应节点,提高diff速度,更高效的更新虚拟dom。 为了在数据变化时强制更新组件,避免“就地复用”带来的副作用。

组件中data为什么是一个函数

组价被复用多次就会创建多个实例, 如果data是对象的话,对象属于引用类型会影响到所有实例,为保证组件不同实例间的data不冲突,data必须为一个函数。

vue文档的风格指南

代码命名规范

  • JavaScript:使用camelCase(驼峰命名)
  • Html:使用kebab-case(-划线命名)

文件命名规范

  • 单文件组件
components/
|- MyComponent.vue

JavaScript顺序

  1. name
  2. components
  3. mixins
  4. props
  5. data
  6. computed
  7. watch
  8. 生命周期(breforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed)
  9. methods

## 元素attribute顺序

  1. v-for
  2. v-if(v-else-if、v-else,v-show)
  3. id
  4. ref
  5. key
  6. v-model
  7. 其他attribute
  8. v-on

props规范

props定义应该尽量详细,至少需要指定其类型

props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {}
  }
}

vue服务端渲染(SSR)

  • 只执行created钩子函数
  • try...catch会造成数据延迟
  • 没有window对象
  • 没有状态管理(入口设置)
window.__SSR_STORE__ = store