• 阿里前端高频vue面试题(边面边更)


    Vue 中 computed 和 watch 有什么区别?

    计算属性 computed
    (1)支持缓存,只有依赖数据发生变化时,才会重新进行计算函数;
    (2)计算属性内不支持异步操作
    (3)计算属性的函数中都有一个 get(默认具有,获取计算属性)和 set(手动添加,设置计算属性)方法;
    (4)计算属性是自动监听依赖值的变化,从而动态返回内容。

    侦听属性 watch
    (1)不支持缓存,只要数据发生变化,就会执行侦听函数;
    (2)侦听属性内支持异步操作
    (3)侦听属性的值可以是一个对象,接收 handler 回调,deep,immediate 三个属性
    (3)监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些其他事情

    vue是如何实现响应式数据的呢?(响应式数据原理)

    Vue2 Object.defineProperty 重新定义 data 中所有的属性, Object.defineProperty 可以使数据的获取与设置增加一个拦截的功能,拦截属性的获取,进行依赖收集。拦截属性的更新操作,进行通知。

    具体的过程:首先Vue使用 initData 初始化用户传入的参数,然后使用 new Observer 对数据进行观测,如果数据是一个对象类型就会调用 this.walk(value) 对对象进行处理,内部使用 defineeReactive 循环对象属性定义响应式变化,核心就是使用 Object.defineProperty 重新定义数据。

    写过自定义指令吗 原理是什么

    指令本质上是装饰器,是 vue 对 HTML 元素的扩展,给 HTML 元素增加自定义功能。vue 编译 DOM 时,会找到指令对象,执行指令的相关方法。

    自定义指令有五个生命周期(也叫钩子函数),分别是 bind、inserted、update、componentUpdated、unbind

    1. bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
    
    2. inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
    
    3. update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
    
    4. componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
    
    5. unbind:只调用一次,指令与元素解绑时调用。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    原理

    1.在生成 ast 语法树时,遇到指令会给当前元素添加 directives 属性

    2.通过 genDirectives 生成指令代码

    3.在 patch 前将指令的钩子提取到 cbs 中,在 patch 过程中调用对应的钩子

    4.当执行指令对应钩子函数时,调用对应指令定义的方法

    如果让你从零开始写一个vuex,说说你的思路

    思路分析

    这个题目很有难度,首先思考vuex解决的问题:存储用户全局状态并提供管理状态API。

    • vuex需求分析
    • 如何实现这些需求

    回答范例

    1. 官方说vuex是一个状态管理模式和库,并确保这些状态以可预期的方式变更。可见要实现一个vuex
    • 要实现一个Store存储全局状态
    • 要提供修改状态所需API:commit(type, payload), dispatch(type, payload)
    1. 实现Store时,可以定义Store类,构造函数接收选项options,设置属性state对外暴露状态,提供commitdispatch修改属性state。这里需要设置state为响应式对象,同时将Store定义为一个Vue插件
    2. commit(type, payload)方法中可以获取用户传入mutations并执行它,这样可以按用户提供的方法修改状态。 dispatch(type, payload)类似,但需要注意它可能是异步的,需要返回一个Promise给用户以处理异步结果

    实践

    Store的实现:

    class Store {
       
        constructor(options) {
       
            this.state = reactive(options.state)
            this.options = options
        }
        commit(type, payload) {
       
            this.options.mutations[type].call(this, this.state, payload)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    vuex简易版

    /**
     * 1 实现插件,挂载$store
     * 2 实现store
     */
    
    let Vue;
    
    class Store {
       
      constructor(options) {
       
        // state响应式处理
        // 外部访问: this.$store.state.***
        // 第一种写法
        // this.state = new Vue({
       
        //   data: options.state
        // })
    
        // 第二种写法:防止外界直接接触内部vue实例,防止外部强行变更
        this._vm = new Vue({
       
          data: {
       
            $$state: options.state
          }
        })
    
        this._mutations = options.mutations
        this._actions = options.actions
        this.getters = {
       }
        options.getters && this.handleGetters(options.getters)
    
        this.commit = this.commit.bind(this)
        this.dispatch = this.dispatch.bind(this)
      }
    
      get state () {
       
        return this._vm._data.$$state
      }
    
      set state (val) {
       
        return new Error('Please use replaceState to reset state')
      }
    
      handleGetters (getters) {
       
        Object.keys(getters).map(key => {
       
          Object.defineProperty(this.getters, key, {
       
            get: () => getters[key](this.state)
          })
        })
      }
    
      commit (type, payload) {
       
        let entry = this._mutations[type]
        if (!entry) {
       
          return new Error(`${
         type} is not defined`)
        }
    
        entry(this.state, payload)
      }
    
      dispatch (type, payload) {
       
        let entry = this._actions[type]
        if (!entry) {
       
          return new Error(`${
         type} is not defined`)
        }
    
        entry(this, payload)
      }
    }
    
    const install = (_Vue) => {
       
      Vue = _Vue
    
      Vue.mixin({
       
        beforeCreate () {
       
          if (this.$options.store) {
       
            Vue.prototype.$store = this.$options.store
          }
        },
      })
    }
    
    
    export default {
        Store, install }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    验证方式

    import Vue from 'vue'
    import Vuex from './vuex'
    // this.$store
    Vue.use(Vuex)
    
    export default new Vuex.Store({
       
      state: {
       
        counter: 0
      },
      mutations: {
       
        
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    发育转录组:什么样的猪肉最好吃
    【算法leetcode】剑指 Offer II 045. 二叉树最底层最左边的值(rust和go重拳出击)
    golang中的接口(数据类型)
    JS超集对TypeScript的Map对象以及联合类型的深入实战
    Vue2.0源码理解(6) - 组件注册
    MySQL——DBCP和C3P0连接池
    electron调用dll文件
    代码随想录 | 单调栈part01 part02 part03
    中央设备状态监控系统CMS如何帮助半导体晶圆厂提高产品良率
    linux系统中三个重要的结构体
  • 原文地址:https://blog.csdn.net/bb_xiaxia1998/article/details/127318325