• 一文梳理Vue面试题


    你有对 Vue 项目进行哪些优化?

    (1)代码层面的优化

    • v-if 和 v-show 区分使用场景
    • computed 和 watch 区分使用场景
    • v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
    • 长列表性能优化
    • 事件的销毁
    • 图片资源懒加载
    • 路由懒加载
    • 第三方插件的按需引入
    • 优化无限列表性能
    • 服务端渲染 SSR or 预渲染

    (2)Webpack 层面的优化

    • Webpack 对图片进行压缩
    • 减少 ES6 转为 ES5 的冗余代码
    • 提取公共代码
    • 模板预编译
    • 提取组件的 CSS
    • 优化 SourceMap
    • 构建结果输出分析
    • Vue 项目的编译优化

    (3)基础的 Web 技术的优化

    • 开启 gzip 压缩
    • 浏览器缓存
    • CDN 的使用
    • 使用 Chrome Performance 查找性能瓶颈

    Vuex中action和mutation的区别

    mutation中的操作是一系列的同步函数,用于修改state中的变量的的状态。当使用vuex时需要通过commit来提交需要操作的内容。mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

    const store = new Vuex.Store({
       
      state: {
       
        count: 1
      },
      mutations: {
       
        increment (state) {
       
          state.count++      // 变更状态
        }
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    当触发一个类型为 increment 的 mutation 时,需要调用此函数:

    store.commit('increment')
    
    
    • 1
    • 2

    而Action类似于mutation,不同点在于:

    • Action 可以包含任意异步操作。
    • Action 提交的是 mutation,而不是直接变更状态。
    const store = new Vuex.Store({
       
      state: {
       
        count: 0
      },
      mutations: {
       
        increment (state) {
       
          state.count++
        }
      },
      actions: {
       
        increment (context) {
       
          context.commit('increment')
        }
      }
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
    所以,两者的不同点如下:

    • Mutation专注于修改State,理论上是修改State的唯一途径;Action业务代码、异步请求。
    • Mutation:必须同步执行;Action:可以异步,但不能直接操作State。
    • 在视图更新时,先触发actions,actions再触发mutation
    • mutation的参数是state,它包含store中的数据;store的参数是context,它是 state 的父级,包含 state、getters

    函数式组件优势和原理

    函数组件的特点

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

    优点

    1. 由于函数式组件不需要实例化,无状态,没有生命周期,所以渲染性能要好于普通组件
    2. 函数式组件结构比较简单,代码结构更清晰

    使用场景:

    • 一个简单的展示组件,作为容器组件使用 比如 router-view 就是一个函数式组件
    • “高阶组件”——用于接收一个组件作为参数,返回一个被包装过的组件

    例子

    Vue.component('functional',{
        // 构造函数产生虚拟节点的
        functional:true, // 函数式组件 // data={attrs:{}}
        render(h){
       
            return h('div','test')
        }
    })
    const vm = new Vue({
       
        el: '#app'
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    源码相关

    // functional component
    if (isTrue(Ctor.options.functional)) {
        // 带有functional的属性的就是函数式组件
      return createFunctionalComponent(Ctor, propsData, data, context, children)
    }
    
    // extract listeners, since these needs to be treated as
    // child component listeners instead of DOM listeners
    const listeners = data.on // 处理事件
    // replace with listeners with .native modifier
    // so it gets processed during parent component patch.
    data.on = data.nativeOn // 处理原生事件
    
    // install component management hooks onto the placeholder node
    installComponentHooks(data) // 安装组件相关钩子 (函数式组件没有调用此方法,从而性能高于普通组件)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    v-model实现原理

    我们在 vue 项目中主要使用 v-model 指令在表单 inputtextareaselect 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖(可以看成是value + input方法的语法糖),v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

    • texttextarea 元素使用 value 属性和 input 事件
    • checkboxradio 使用 checked 属性和 change 事件
    • select 字段将 value 作为 prop 并将 change 作为事件

    所以我们可以v-model进行如下改写:

    <input v-model="sth" />
    
    <input :value="sth" @input="sth = $event.target.value" />
    
    • 1
    • 2
    • 3

    当在input元素中使用v-model实现双数据绑定,其实就是在输入的时候触发元素的input事件,通过这个语法糖,实现了数据的双向绑定

    • 这个语法糖必须是固定的,也就是说属性必须为value,方法名必须为:input
    • 知道了v-model的原理,我们可以在自定义组件上实现v-model
    //Parent
    <template>
      {
       {
       num}}
      <Child v-model="num">
    </template>
    export default {
       
      data(){
       
        return {
       
          num: 0
        }
      }
    }
    
    //Child
    <template>
      <div @click="add">Add</div>
    </template>
    export default {
       
      props: ['value'], // 属性必须为value
      methods:{
       
        add(){
       
          // 方法名为input
          this.$emit('input', this.value + 1)
        }
      }
    }
    
    • 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

    原理

    会将组件的 v-model 默认转化成value+input

    const VueTemplateCompiler = require('vue-template-compiler'); 
    const ele = VueTemplateCompiler.compile(''); 
    
    // 观察输出的渲染函数:
    // with(this) { 
    //     return _c('el-checkbox', { 
    //         model: { 
    //             value: (check), 
    //             callback: function ($$v) { check = $$v }, 
    //             expression: "check" 
    //         } 
    //     }) 
    // }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    // 源码位置 core/vdom/create-component.js line:155
    
    function transformModel (options, data: any) {
        
        const prop = (options.model && options.model.prop) || 'value' 
        const event = (options.model && options.model.event) || 'input' 
        ;(data.attrs || (data.attrs = {
       }))[prop] = data.model.value 
        const on = data.on || (data.on = {
       }) 
        const existing = on[event] 
        const callback = data.model.callback 
        if (isDef(existing)) {
        
            if (Array.isArray(existing) ? existing.indexOf(callback) === -1 : existing !== callback ) {
       
                on[event] = [callback].concat(existing) 
            } 
        } else {
        
            on[event] = callback 
        } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    原生的 v-model,会根据标签的不同生成不同的事件和属性

    const VueTemplateCompiler = require('vue-template-compiler'); 
    const ele = VueTemplateCompiler.compile('');
    
    // with(this) { 
    //     return _c('input', { 
    //         directives: [{ name: "model", rawName: "v-model", value: (value), expression: "value" }], 
    //         domProps: { "value": (value) },
    //         on: {"input": function ($event) { 
    //             if ($event.target.composing) return;
    //             value = $event.target.value
    //         }
    //         }
    //     })
    // }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    编译时:不同的标签解析出的内容不一样 platforms/web/compiler/directives/model.js

    if (el.component) {
        
        genComponentModel(el, value, modifiers) // component v-model doesn't need extra runtime 
        return false 
    } else if (tag === 'select') {
        
        genSelect(el, value, modifiers) 
    } else if (tag === 'input' && type === 'checkbox') {
        
        genCheckboxModel(el, value, modifiers) 
    } else if 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    待办事项 数据库表设计
    2022护眼产品展,北京眼健康展,眼科医学展,近视矫正设备展
    贪吃蛇项目实践!(下)
    nginx中sent_timeout属性使用注意事项
    nc反弹以及中 &>、0>&1是什么意思
    Vue模板语法
    R语言使用match函数获取向量中特定值的位置(position of a particular value)、which.min函数获取向量中最小值的位置
    MogaFX外汇短缺可能会促使SSA进一步出现债务重组趋势
    npm i 报错或者卡顿 range manifest for 解决
    Ubuntu-基础工具配置
  • 原文地址:https://blog.csdn.net/bb_xiaxia1998/article/details/127644821