2022年Vue面试题

本次让我们系统的熟悉vue的面试常用题目,无论是给准备面试还是准备跳槽的小伙伴,一个学习以及温故知新的版块。这其中加入了我的理解,我尽量用白话文和易懂的语言形式进行解释,如果有地方解释的不正确或者不准确的情况,还请大家不吝赐教。

2022年大环境的不景气,让我们用知识充实自己,面对生活的一次次挑战与考验,加油!

入门级:

1:什么是mvvm?

MVVM是Model-View-ViewModel的简写,是M-V-VM三部分组成。它本质上是MVC的改进版本,MVVM就是将其中的View的状态和行为抽象化,其中ViewModel将视图 UI 和业务逻辑分开,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

MVVM采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,model中数据变化也将会自动展示在页面上。把Model和View关联起来的就是ViewModel。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。

让我们开发人员可以专注于业务逻辑方面(ViewModel),对于数据的绑定与展示(自动更新dom),不需要过多的dom操作。可以理解为数据(medel)驱动UI(view),而UI(view)的改变也会影响数据(medel)。他们之间就是靠ViewModel来实现。

因此开发者只需要关注业务逻辑,不需要手动操作 DOM,也不需要关注数据状态的同步问题,这些都由 MVVM 统一管理。

2:为什么要用vue?

1.虚拟dom:dom操作是非常的消耗性能的,不再使用原生的dom操作节点的方式,模拟一个虚拟dom树,运用deff算法,只更新修改的dom节点,极大的释放了dom操作。

2.视图,数据,结构的分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作(mvvm)

3.组件化:把一个单页应用中的各个模块拆分到一个个单独的组件中,各个组件有自己的行为逻辑以及自己的样式,相互不干扰。便于开发,以及后期维护。相同组件的公用也大大节约了开发成本。

3:vue的生命周期(11个钩子函数)


1.beforeCreate(创建前):在此生命周期函数执行的时候,data和methods中的数据还没有初始化。

2.created(创建后):在这个生命周期中,data 和 methods 都已经被初始化好了,可以访问到data中的数据以及methods的方法。

3.beforeMount(载入前):在此生命周期函数执行的时候,模板已经在内存中编译好了,但是尚未挂载到页面中去,此时页面还是旧的。

4.mounted(载入后):此时页面和内存中是最新数据,dom树创建,此时才可以操作dom节点。

5.beforeUpdate(更新前):顾名思义,这个时候页面正准备进行更新,只是还未开始更新动作,所以页面中的数据还是旧的,但是data中的数据已经是新的,只是页面并未和最新数据同步。

6.Updated(更新后):此时页面显示数据和最新的 data 数据同步。

7.beforeDestroy(销毁前):组件销毁前的钩子函数,此时实例上的data,methods,以及过滤器等都处于可用状态。我们一般可以在这个钩子内清除当前组件的定时器(clearInterval() )

8.destroyed(销毁后):此时组件已经被完全销毁,实例中的所有的数据、方法、属性、过滤器…等都已经不可用了

// 以上8个生命周期钩子函数是我们常用的钩子函数,接下来的3个钩子函数可以在特定的时候使用,方便我们理解

9.activated(组件激活时):在使用被keep-alive缓存的组件时,进入函数。如果一个子页面或者一个组件被keep-alive包含,那么当这个页面或组件第一次时会走一次完整的生命周期,当此组件无法被销毁。等重复使用的时候,会从缓存里面直接调出,此时组件不在执行前4个生命周期钩子(因为它并没有被销毁,不需要重新创建)。取而代之的是进入activated钩子函数。表示该页面或组件被激活。

10.deactivated(组件未激活时):实例没有被激活时(同9)。

11.errorCaptured(错误调用):当捕获一个来自后代组件的错误时被调用

注意:有很多面试会问父子组件创建销毁的生命周期顺序:
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

即父组件走到beforeMount 后,开始走完子组件的完整生命周期,然后再走父组件mounted

这样理解:
1.有父才有子,所以一开始是父组件先创建实例。
2.mounted本身就是挂在到页面上的钩子,所以必须要等所有的子组件完成后再一起挂载到页面中。(既然是父,当然要包含所有的子)

4:watch、computed 和 methods 的区别

  • methods 方法:组件内部的业务逻辑方法的集合
  • computed 计算属性:依赖已有的变量来计算一个目标变量,例如根据data的变量来计算新的变量,用来格式化。或者引用store,...mapState的语法糖引用state。(computed是有缓存的,注意不能进行异步操作)
  • watch 监听:监听某一个变量的变化,并且执行相应的回调函数(watch没有缓存,目标变化一次执行一次,可以进行异步操作)

许多面试官喜欢问computed 和watch的区别,这里请多加理解

5.Vue.js的特点

  • 简洁:页面由HTML模板+Json数据+Vue实例组成,结构简单易懂
  • 数据驱动:自动计算属性和追踪依赖的模板表达式
  • 组件化:用组件来构造页面,可复用,维护方便
  • 轻量:代码量小,不依赖其他库
  • 快速:精确有效批量 DOM 更新
  • 模板友好:可通过 npm,bower 等多种方式安装,很容易融入

6:插槽的理解

插槽用于决定将所携带的内容,插入到子组件指定的某个位置,但内容必须在父组件中子组件的标签内定义,在子组件中用标签接收。slot 是组件内部的占位符。即组件编写时留给组件使用者的一个插入口。使用者可以在此编写自己的html格式以及样式,插入的位置由编写者制定

7.Vue组件之间传参

1.父传子:

  • 父组件通过props方式传递数据
  • 父组件也可以直接选择子节点的形式选中子组件的实例
this.$refs.nodeName // refs是根据组件名字来取的响应组件的属性
this.$children[2] // 返回一个数组(使用几率小,一般不这样调用)

2.子传父:

  • 子组件用$emit方法,触发父组件的监听
  • this.$parnet获取当前组件的父组件实例

3.兄弟组件之间(这里写的是兄弟组件之间,实际上是所有组件之间都可以,包括父子)

  • 用一个事件总线,evenBus。新建一个空的vue实例作事件总线(为了方便调用一般绑定到vue原型),然后用$on监听事件,用$emit触发事件。
this.$eventBus.$on('sayName',(data)=>{
  console.log(data)
}) // 监听事件总线中sayName方法
this.$eventBus.$emit('sayName',data)

详细讲解请移步到:https://www.jianshu.com/p/267e17c59d32

  • Vuex:Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式。在下面的复习中我们会详细讲解到

4.浏览器本地缓存,例如localStorage,sessionStorage

8.vue 组件中的 data 为什么是一个函数

data 是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响。Object 是引用数据类型,如果不用 function 返回,每个组件的 data 都是内存的同一个地址(储存的是地址,指针,此处可以复习浅拷贝和深拷贝),一个数据改变了其他也改变了。
理解就是运用了function的函数作用域让他变成局部作用域,这样每复用一次组件,就会返回一份新的 data,类似于给每个组件实例创建一个私有的数据空间

9.路由懒加载(首页加载优化)

在单页应用中,如果没有应用懒加载,运用 webpack 打包后的文件将会异常的大,造成进入首页时,需要加载的内容过多,延时过长,不利于用户体验,而运用懒加载则可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时

原理:vue 异步组件技术:异步加载,vue-router 配置路由 , 使用 vue 的异步组件技术 , 实现按需加载


import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'
Vue.use(Router)
export default new Router({
  routes: [
//     {
//       path: '/',
//       name: 'HelloWorld',
//       component: HelloWorld
//     }
        {
          path: '/',
          name: 'HelloWorld',
          component: () => import('@/components/HelloWorld.vue')
        }
  ]
})

10:请说出 vue.cli 项目中 src 目录每个文件夹和文件的用法`

assets 文件夹是放静态资源;
components 是放组件;
router 是定义路由相关的配置;
store vuex模块;
view 视图;
app.vue 是一个应用主组件;
main.js 是入口文件

11.Vue 中 key 值的作用

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

12:vue 的指令

  • v-bind:给元素绑定属性,简写为:

  • v-on:给元素绑定事件,简写为@

  • v-html:给元素绑定数据,且该指令可以解析 html 标签

  • v-text:给元素绑定数据,不解析标签

  • v-model:数据双向绑定

  • v-for:遍历数组

  • v-show:条件渲染指令,将不符合条件的数据隐藏(display:none)

  • v-if:条件渲染指令,动态在 DOM 内添加或删除 DOM 元素(无节点)

  • v-else:条件渲染指令,必须跟 v-if 成对使用

  • v-else-if:判断多层条件,必须跟 v-if 成对使用

  • v-cloak:解决插值闪烁问题

  • v-once:只渲染元素或组件一次

  • v-pre:跳过这个元素以及子元素的编译过程,以此来加快整个项目的编译速度

13.v-for 与 v-if

因为v-for的优先级高于v-if,势必会先遍历数组,然后再判断是否显示,这样就会影响速度,尤其是只需要渲染很小一部分的时候,渲染了许多无用的节点,增加许多无用的dom操作,建议用computed先把需要的数组格式化出来

<div v-for="item in list">
    {{item}}
</div>

computed() {
    list() {
        return [1, 2, 3, 4, 5, 6, 7].filter(item => item !== 3)
    }
 }

14.Vue怎么兼容IE

使用 babel-polyfill 插件省省吧,2022年6月16日起ie都退役了

15.Vue 怎么重置 data

在很多情况下我们会遇到初始化data的时候,比如在调用element的dialog组件时(组件是v-show控制,会保留之前的状态)

Object.assign(this.$data, this.$options.data()) // 初始化data

16.route 和 router

  • route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。
    route查询修改当前路由的对象
  • router 是“路由实例对象”,包括了路由的跳转方法(push、go),钩子函数等。
    router获取当前路由实例,调用方法

17.Vue的修饰符有哪些?


常用修饰符:

  • .stop 阻止事件继续传播
  • .prevent 阻止标签默认行为
  • .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
  • .self 只当在 event.target 是当前元素自身时触发处理函数
  • .once 事件将只会触发一次
  • .passive 告诉浏览器你不想阻止事件的默认行为
  • .right 使用鼠标右键触发事件@click.right

中级:

1.虚拟 DOM 原理

虚拟 DOM,其实就是用对象的方式取代真实的DOM操作,把真实的DOM操作放在内存当中,在内存中的对象里做模拟操作。当页面打开时浏览器会解析 HTML 元素,构建一颗 DOM树,将状态全部保存起来,在内存当中模拟我们真实的 DOM操作,操作完后又会生成一颗 dom 树,两颗DOM树进行比较,根据 diff 算法比较两颗 DOM树不同的地方,只渲染一次不同的地方。
用diff算法把虚拟DOM和真实DOM比较,找出不同的地方,页面只渲染不同的地方

2:nextTick 的理解

Vue 是异步修改 DOM 的,并且不鼓励开发者直接接触 DOM,但是有时候需要必须对数据更改后的 DOM 元素做相应的处理,但是获取到的 DOM 数据并不是更改后的数据,这时候就需要 this.$nextTick();
很常见一个例子,在数据变化后马上要使用ref进行节点操作,由于vue是异步修改dom的,所以在数据变化后可能没有找到需要操作的dom,故而报错

<div ref="mydom"  v-if="isShow"></div>

  methods() {
    this.isShow = true;
    this.$nextTick(()=>{
      this.$refs.mydom.play() // 等待最新的dom更新了之后的回调,此时已经有了mydom节点,可以对其进行dom操作
    })
  },

3.不需要响应式的数据应该怎么处理?

在我们的Vue开发中,会有一些数据,从始至终都未曾改变过,这种死数据,既然不改变,那也就不需要对他做响应式处理了,不然只会做一些无用功消耗性能,比如一些写死的下拉框,写死的表格数据,这些数据量大的死数据,如果都进行响应式处理,那会消耗大量性能。

// 方法一:将数据定义在return 之外(初始化时期只会对data内的数据绑定getter和setter)
data () {
    this.list1 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }
    this.list2 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }
    this.list3 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }
    this.list4 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }
    this.list5 = { xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx }
    return {}
 }
    
// 方法二:Object.freeze()
data () {
    return {
        list1: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}),
        list2: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}),
        list3: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}),
        list4: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}),
        list5: Object.freeze({xxxxxxxxxxxxxxxxxxxxxxxx}),
    }
 }

4.vue 中的双向绑定原理

概念:双向绑定是vue的一个核心功能,所谓双向绑定就是当视图发生改变的时候传递给VM(ViewModel ),让数据得到更新,当数据发生改变的时候传给VM(ViewModel ),使得视图发生变化。

那么vue怎么做到的呢?
observer(观察者),劫持监听所有属性,什么意思呢?

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

先简单的实现一个js的双向数据绑定来熟悉一下Object.defineProperty()方法

 <input type="text" id="in"/>
    输入的值为:<span id="out"></span>
    <script>
        var int = document.getElementById('in');
        var out = document.getElementById('out');
        var obj = {};
        Object.defineProperty(obj, 'msg', {
            enumerable: true,
            configurable: true,
            set (newVal) {
                out.innerHTML = newVal;
            }
        })
        int.addEventListener('input', function(e) {
            obj.msg = e.target.value;
        })

/*通过给in输入框添加事件监听input来触发obj对象的set方法,
而set在修改了访问器属性的同时,也修改了dom样式,改变了span标签内的文本。*/

5.vue3的了解

大致有三个点:
1.关于提出的新 API setup()函数。
2.对于 Typescript 的支持。
3.最后说了关于替换 Object.defineProperty 为 Proxy 的支持。详细说了下关于 Proxy 代替带来的性能上的提升,因为传统的原型链拦截的方法,无法检测对象及数组的一些更新操作,但使用 Proxy 又带来了浏览器兼容问题。

6.vue-cli 替我们做了哪些工作

vue-cli 是基于 Vue.js 进行快速开发的完整系统,也可以理解成是很多 npm 包的集合。
vue-cli 完成的功能:

  • .vue 文件 --> .js 文件
  • ES6 语法 --> ES5 语法
  • Sass,Less,Stylus --> CSS
  • 对 jpg,png,font 等静态资源的处理
  • 热更新
  • 定义环境变量,区分 dev 和 production 模式
  • 如果开发者需要补充或修改默认设置,需要在 package.json 同级下新建一个 vue.config.js 文件

7.axios拦截器

响应拦截

axios.interceptors.response.use((response)=>{
    //对响应数据做点什么
    return response.data
},(error)=>{
    //对错误响应做点什么
    return Promise.reject(error)
})

请求拦截

axios.interceptors.request.use((config)=>{
    //在发送请求之前做些什么
    return config
},(error)=>{
    //对请求错误做些什么
    return Promise.reject(error)
})

14:vue-router 路由钩子函数是什么 执行顺序是什么

路由钩子的执行流程, 钩子函数种类有:全局守卫、路由守卫、组件守卫

完整的导航解析流程:

  • 导航被触发。
  • 在失活的组件里调用 beforeRouteLeave 守卫。
  • 调用全局的 beforeEach 守卫。
  • 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  • 在路由配置里调用 beforeEnter。
  • 解析异步路由组件。
  • 在被激活的组件里调用 beforeRouteEnter。
  • 调用全局的 beforeResolve 守卫 (2.5+)。
  • 导航被确认。
  • 调用全局的 afterEach 钩子。
  • 触发 DOM 更新。
  • 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入

1.全局守卫:

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/home'
  },
  {
    path: '/home',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  }
]

const router = new VueRouter({
  routes
})
// 跳转路由之前
router.beforeEach((to,from,next)=>{
  // ..............
  next()
})
// 跳转路由之后
router.afterEach((to,from,next)=>{
  // ..............
  next()
})

export default router

2.单个路由独享的守卫

const routes = [
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue'),
    beforeEach:((to,from,next)=>{
      // ..............
      next()
    })
  }
]

3.组件级守卫(beforeRouteEnter)组件级的守卫写在页面组件中,与data,methods同级。如图

export default {
  data(){
    return{}
  },
  created:{},
  components: {},
  methods:{},
  beforeRouteEnter(to,from,next){
      // ..............
  next()
  }
};

15.Vuex的理解重点

定义:Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式储存管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
使用场景:需要构建一个中大型单页应用,您很可能会考虑如何更好的在组件外部管理状态,Vuex将会成为自然而然的选择。
优点:当你在state中定义了一个数据之后,可以在所在项目中的任何一个组件里进行获取、进行修改、并且你的修改可以得到全局的响应变更。(全局变量理解方式)

主要包括以下几个模块:

  • State:定义了应用状态的数据结构,可以在这里设置默认的初始状态。
  • Getter:允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
  • Mutation:是唯一更改 store 中状态的方法,且必须是同步函数
  • Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作
  • Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中。大型项目时可以把store也拆分多个模块,每个store包含自己的state,getter,mutation,action

Vuex的运行机制:Vuex提供数据(state)来驱动试图(vue components),通过dispath派发actions,在其中可以做一些异步的操作,然后通过commit来提交mutations,最后mutations来更改state。

import Vuex from 'vuex';
import Vue from 'vue';

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
  },
  mutations: {
    increment(state, val) {
      console.log(state);
    },
  },
  actions: {
    addCount(context) {
      console.log(context);
      // 可以包含异步操作
      // context 是一个与 store 实例具有相同方法和属性的 context 对象
    },
  },
  getters: {
    doneTodos(state) {
      return state;
    }
  }
});

export default store;

16:Vuex 页面刷新数据丢失怎么解决

我们都知道,vuex是作为一个公共的状态管理集合,但是他是存储在内存中的,在浏览器中,刷新页面会清空一次内存。显然对于一些公共的状态,我们是不希望刷新清空的,这里就有了vuex数据持久化的一个问题

需要做 vuex 数据持久化 一般使用本地存储的方案来保存数据 可以自己设计存储方案 也可以使用第三方插件

1.推荐使用 vuex-persist 插件,它就是为 Vuex 持久化存储而生的一个插件。不需要你手动存取 storage ,而是直接将状态保存至 cookie 或者 localStorage 中
(注实际开发中使用sessionStorage来保存,原因是localStorage在同一浏览器中多个账户登录保存到localStroage会出问题)

2.或者手动把vuex数据存储在sessionStorage中

window.addEventListener('beforeunload', e => {
  console.log('页面进行了刷新或者关闭')
// 保存vuex操作
})
// 注意要卸载监听事件
window.removeEventListener('beforeunload', e =>{})

17.你都用过哪些vue性能优化

这里只列举针对 Vue 的性能优化 整个项目的性能优化是一个大工程 可以另写一篇性能优化的文章了

1.减少http请求
2.对象层级不要过深,否则性能就会差
3.不需要响应式的数据不要放到 data的return 中(可以用 Object.freeze() 冻结数据)
4.v-if 和 v-show 区分使用场景
5.computed 和 watch 区分使用场景
6.v-for 遍历必须加 key,key 最好是 id 值,且避免同时使用 v-if
7.大数据列表和表格性能优化-虚拟列表/虚拟表格
8.防止内部泄漏,组件销毁后把全局变量和事件销毁
9.图片懒加载
10.路由懒加载(首页加载优化)
11.第三方插件的按需引入
12.适当采用 keep-alive 缓存组件
13.防抖、节流运用
14.服务端渲染 SSR or 预渲染
15.插件引入尽量不要全局引入(首页加载优化)

18.描述下vue从初始化页面=>修改数据=>刷新页面 UI 过程?

1.当 Vue 进入初始化阶段时,一方面 Vue 会遍历 data 中的属性,并用 Object.defineProperty 将它转化成 getter/setterd 的形式,实现数据劫持;
2.另一方面,Vue 的指令编译器 Compiler 对元素节点的各个指令进行解析,初始化视图,并订阅 Watcher 来更新视图,此时 Watcher 会将自己添加到消息订阅器 Dep 中,此时初始化完毕。
3.当数据发生变化时,触发 Observer 中 setter 方法,立即调用 Dep.notify( ),Dep 这个数组开始遍历所有的订阅者,并调用其 update 方法,Vue 内部再通过 diff 算法,patch 相应的更新完成对订阅者视图的改变。

19.给对象添加了新的属性,data改变了,但是页面上没有改变,为什么?

这里用到$set

原因:vue在创建实例的时候把data深度遍历所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。让 Vue 追踪依赖,在属性被访问和修改时通知变化。所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。

vue.$set 是能让 vue 知道你添加了属性, 它会给你做处理

change(){
  this.$set(this.list,1,0);
}

进阶级

1.说一下Vue.mixin

在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立,可以通过 Vue 的 mixin 功能抽离公共的业务逻辑,原理类似“对象的继承”,当组件初始化时会调用 mergeOptions 方法进行合并,采用策略模式针对不同的属性进行合并。当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”
详细请点击https://www.jianshu.com/p/772d67305f98

2.keep-alive 使用场景和原理

keep-alive 是 Vue 内置的一个组件,可以实现组件缓存,当组件切换时不会对当前组件进行卸载。

  • 常用的两个属性 include/exclude,允许组件有条件的进行缓存。
  • 两个生命周期 activated/deactivated,用来得知当前组件是否处于活跃状态。
  • keep-alive 的中还运用了 LRU(最近最少使用) 算法,选择最近最久未使用的组件予以淘汰

3.函数式组件使用场景和原理

1.函数式组件需要在声明组件是指定 functional:true
2.不需要实例化,所以没有this,this通过render函数的第二个参数context来代替
3.没有生命周期钩子函数,不能使用计算属性,watch
4.不能通过$emit对外暴露事件,调用事件只能通过context.listeners.click的方式调用外部传入的事件
5.因为函数式组件是没有实例化的,所以在外部通过ref去引用组件时,实际引用的是HTMLElement
6.函数式组件的props可以不用显示声明,所以没有在props里面声明的属性都会被自动隐式解析为prop,而普通组件所有未声明的属性都解析到$attrs里面,并自动挂载到组件根元素上面(可以通过inheritAttrs属性禁止)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容