框架面试课-Vue使用

1.      Vue使用

1.1.       2-1 vue使用-考点串讲

1.1.1.    Vue 使用

·        基本使用,组件使用 —— 常用,必须会

·        高级特性 —— 不常用,但体现深度

·        Vuex Vue-router 使用

1.1.2.    自己去看文档不行吗?

·        行。但这种一种最低效的方式

·        文档是一个备忘录,给会用的人查阅,并不是入门教程

·        文档全面冗长且细节过多,不能突出面试考点

1.2.       2-2 2-3 vue基本使用

1.2.1.    Vue 基本使用

·        日常使用,必须掌握,面试必考(不一定全考)

·        梳理知识点,从冗长的文档中摘出考点和重点

·        考察形式不限(参考后面的面试真题),但都在范围之内

1.2.2.    vue基本知识点串讲

·        指令、插值

      插值、表达式

      指令、动态属性

      v-html:会有 XSS 风险,会覆盖子组件

      参考代码

      参考代码图片

         

desc

      参考代码

      <template>
    <div>
        <p>
文本插值 {{message}}</p>
        <p>JS
表达式 {{ flag ? 'yes' : 'no' }} (只能是表达式,不能是 js 语句)</p>

        <p :id="dynamicId">
动态属性 id</p>

        <hr/>
        <p v-html="rawHtml">
            <span>
xss 风险</span>
            <span>
【注意】使用 v-html 之后,将会覆盖子元素</span>
        </p>
        <!--
其他常用指令后面讲 -->
    </div>
</template>

<script>
export default {
    data() {
        return {
            message: 'hello vue',
            flag: true,
            rawHtml: '
指令 - 原始 html <b>加粗</b> <i>斜体</i>',
            dynamicId: `id-${Date.now()}`
        }
    }
}
</script>

·        computed watch

      computed

      computed 有缓存,data 不变则不会重新计算

      参考代码

      参考代码图片

         

desc

      参考代码

      <template>
    <div>
        <p>num {{num}}</p>
        <p>double1 {{double1}}</p>
        <input v-model="double2"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 20
        }
    },
    computed: {
        double1() {
            return this.num * 2
        },
        double2: {
            get() {
                return this.num * 2
            },
            set(val) {
                this.num = val/2
            }
        }
    }
}
</script>

      watch

      watch 如何深度监听?

      参考代码

      参考代码图片

         

desc

      参考代码

      <template>
    <div>
        <input v-model="name"/>
        <input v-model="info.city"/>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: '
双越',
            info: {
                city: '
北京'
            }
        }
    },
    watch: {
        name(oldVal, val) {
            // eslint-disable-next-line
            console.log('watch name', oldVal, val) //
值类型,可正常拿到 oldVal val
        },
        info: {
            handler(oldVal, val) {
                // eslint-disable-next-line
                console.log('watch info', oldVal, val) //
引用类型,拿不到 oldVal 。因为指针相同,此时已经指向了新的 val
            },
            deep: true //
深度监听
        }
    }
}
</script>

      watch 监听引用类型,拿不到 oldVal

·        class style

      使用动态属性

      使用驼峰式写法

      参考代码

      参考代码图片

         

desc

      参考代码

      <template>
    <div>
        <p :class="{ black: isBlack, yellow: isYellow }">
使用 class</p>
        <p :class="[black, yellow]">
使用 class (数组)</p>
        <p :style="styleData">
使用 style</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            isBlack: true,
            isYellow: true,

            black: 'black',
            yellow: 'yellow',

            styleData: {
                fontSize: '40px', //
转换为驼峰式
                color: 'red',
                backgroundColor: '#ccc' //
转换为驼峰式
            }
        }
    }
}
</script>

<style scoped>
    .black {
        background-color: #999;
    }
    .yellow {
        color: yellow;
    }
</style>

·        条件渲染

      v-if v-else 的用法,可使用变量,也可以使用 === 表达式

      v-if v-show 的区别?

      v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和创建,故v-show性能更好一点。

      v-if v-show 的使用场景?

      v-if v-show 都能控制dom元素在页面的显示

      v-if 相比 v-show 开销更大的(直接操作dom节点增加与删除)

      如果在运行时条件很少改变,则使用 v-if 较好

      如果需要非常频繁地切换,则使用 v-show 较好

      参考代码

      参考代码图片

         

desc

      参考代码

      <template>
    <div>
        <p v-if="type === 'a'">A</p>
        <p v-else-if="type === 'b'">B</p>
        <p v-else>other</p>

        <p v-show="type === 'a'">A by v-show</p>
        <p v-show="type === 'b'">B by v-show</p>
    </div>
</template>

<script>
export default {
    data() {
        return {
            type: 'a'
        }
    }
}
</script>

·        循环(列表)渲染

      如何遍历对象? —— 也可以用 v-for

      key 的重要性。key 不能乱写(如 random 或者 index

      v-for v-if 不能一起使用!

      v-for优先级比v-if

      参考代码

      参考代码图片

         

desc

      参考代码

      <template>
    <div>
        <p>
遍历数组</p>
        <ul>
            <li v-for="(item, index) in listArr" :key="item.id">
                {{index}} - {{item.id}} - {{item.title}}
            </li>
        </ul>
        <p>
遍历对象</p>
        <ul >
            <li v-for="(val, key, index) in listObj" :key="key">
                {{index}} - {{key}} -  {{val.title}}
            </li>
        </ul>
    </div>
</template>

<script>
export default {
    data() {
        return {
            flag: false,
            listArr: [
                { id: 'a', title: '
标题1' }, // 数据结构中,最好有 id ,方便使用 key
                { id: 'b', title: '
标题2' },
                { id: 'c', title: '
标题3' }
            ],
            listObj: {
                a: { title: '
标题1' },
                b: { title: '
标题2' },
                c: { title: '
标题3' },
            }
        }
    }
}
</script>

·        事件

      event 参数,自定义参数

      【观察】事件被绑定到哪里?

      1. event 是原生的

      2. 事件被挂载到当前元素

      参考代码

      参考代码图片

         

desc

         

desc

      参考代码

      <template>
    <div>
        <p>{{num}}</p>
        <button @click="increment1">+1</button>
        <button @click="increment2(2, $event)">+2</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            num: 0
        }
    },
    methods: {
        increment1(event) {
            // eslint-disable-next-line
            console.log('event', event, event.__proto__.constructor) //
是原生的 event 对象
            // eslint-disable-next-line
            console.log(event.target)
            // eslint-disable-next-line
            console.log(event.currentTarget) //
注意,事件是被注册到当前元素的,和 React 不一样
            this.num++
            // 1. event
是原生的
            // 2.
事件被挂载到当前元素
            //
DOM 事件一样
        },
        increment2(val, event) {
            // eslint-disable-next-line
            console.log(event.target)
            this.num = this.num + val
        },
        loadHandler() {
            // do some thing
        }
    },
    mounted() {
        window.addEventListener('load', this.loadHandler)
    },
    beforeDestroy() {
        //
【注意】用 vue 绑定的事件,组建销毁时会自动被解绑
        //
自己绑定的事件,需要自己销毁!!!
        window.removeEventListener('load', this.loadHandler)
    }
}
</script>

·        事件修饰符

      参考代码图片

         

desc

·        按键修饰符

      参考代码图片

         

desc

·        表单

      v-model

      常见表单项 textarea checkbox radio select

      修饰符 lazy number trim

      参考代码

      参考代码图片

         

desc

         

desc

      参考代码

      <template>
    <div>
        <p>
输入框: {{name}}</p>
        <input type="text" v-model.trim="name"/>  
        <input type="text" v-model.lazy="name"/>   <!--
防抖 -->
        <input type="text" v-model.number="age"/>

        <p>
多行文本: {{desc}}</p>
        <textarea v-model="desc"></textarea>
        <!--
注意,<textarea>{{desc}}</textarea> 是不允许的!!! -->

        <p>
复选框 {{checked}}</p>
        <input type="checkbox" v-model="checked"/>

        <p>
多个复选框 {{checkedNames}}</p>
        <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
        <label for="jack">Jack</label>
        <input type="checkbox" id="john" value="John" v-model="checkedNames">
        <label for="john">John</label>
        <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
        <label for="mike">Mike</label>

        <p>
单选 {{gender}}</p>
        <input type="radio" id="male" value="male" v-model="gender"/>
        <label for="male">
</label>
        <input type="radio" id="female" value="female" v-model="gender"/>
        <label for="female">
</label>

        <p>
下拉列表选择 {{selected}}</p>
        <select v-model="selected">
            <option disabled value="">
请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>

        <p>
下拉列表选择(多选) {{selectedList}}</p>
        <select v-model="selectedList" multiple>
            <option disabled value="">
请选择</option>
            <option>A</option>
            <option>B</option>
            <option>C</option>
        </select>
    </div>
</template>

<script>
export default {
    data() {
        return {
            name: '
双越',
            age: 18,
            desc: '
自我介绍',

            checked: true,
            checkedNames: [],

            gender: 'male',

            selected: '',
            selectedList: []
        }
    }
}
</script>

1.2.3.    总结

·        必须掌握,否则面试不会通过

·        重点和考点

1.3.       2-4 vue父子组件如何通讯

1.3.1.    props $emit

·        props

      父组件向子组件传递一个信息

·        $emit

      子组件调用父组件的事件

1.3.2.    2-5如何用自定义事件进行vue组件通讯

·        组件间通讯 - 自定义事件

      绑定自定义事件

      参考代码图片

         

desc

      触发自定义事件

      参考代码图片

         

desc

         

desc

      及时销毁,否则可能造成内存泄露

      参考代码图片

         

desc

      注意事项:调用父组件的事件和调用自定义事件是不一样的

1.3.3.    2-6 vue父子组件生命周期调用顺序

·        组件生命周期

      挂载阶段

      参考代码图片

         

desc

      index为父组件

      list为子组件

      更新阶段

      参考代码图片

         

desc

      index为父组件

      list为子组件

      销毁阶段

      删除子组件触发生命周期顺序:

      beforeUpdate => beforeDestroy => destroyed => updated

·        生命周期(父子组件)

      在生命周期中,created表示初始化完,mounted,表示渲染完

      vue的生命周期函数参考图片

         

desc

      父组件初始化完,再初始化子组件,子组件渲染完,再渲染父组件

      参考代码图片

         

desc

         

desc

1.3.4.    参考代码

·        子组件

      input.vue

      <template>
    <div>
        <input type="text" v-model="title"/>
        <button @click="addTitle">add</button>
    </div>
</template>

<script>
import event from './event'

export default {
    data() {
        return {
            title: ''
        }
    },
    methods: {
        addTitle() {
            //
调用父组件的事件
            this.$emit('add', this.title)

            //
调用自定义事件
            event.$emit('onAddTitle', this.title)

            this.title = ''
        }
    }
}
</script>

      List.vue

      <template>
    <div>
        <ul>
            <li v-for="item in list" :key="item.id">
                {{item.title}}

                <button @click="deleteItem(item.id)">
删除</button>
            </li>
        </ul>
    </div>
</template>

<script>
import event from './event'

export default {
    // props: ['list']
    props: {
        // prop
类型和默认值
        list: {
            type: Array,
            default() {
                return []
            }
        }
    },
    data() {
        return {

        }
    },
    methods: {
        deleteItem(id) {
            this.$emit('delete', id)
        },
        addTitleHandler(title) {
            // eslint-disable-next-line
            console.log('on add title', title)
        }
    },
    created() {
        // eslint-disable-next-line
        console.log('list created')
    },
    mounted() {
        // eslint-disable-next-line
        console.log('list mounted')

        //
绑定自定义事件
        event.$on('onAddTitle', this.addTitleHandler)
    },
    beforeUpdate() {
        // eslint-disable-next-line
        console.log('list before update')
    },
    updated() {
        // eslint-disable-next-line
        console.log('list updated')
    },
    beforeDestroy() {
        //
及时销毁,否则可能造成内存泄露
        event.$off('onAddTitle', this.addTitleHandler)
    }
}
</script>

      event.js

      import Vue from 'vue'

export default new Vue()

·        父组件

      index.vue

      <template>
    <div>
        <Input @add="addHandler"/>
        <List :list="list" @delete="deleteHandler"/>
    </div>
</template>

<script>
import Input from './Input'
import List from './List'

export default {
    components: {
        Input,
        List
    },
    data() {
        return {
            list: [
                {
                    id: 'id-1',
                    title: '
标题1'
                },
                {
                    id: 'id-2',
                    title: '
标题2'
                }
            ]
        }
    },
    methods: {
        addHandler(title) {
            this.list.push({
                id: `id-${Date.now()}`,
                title
            })
        },
        deleteHandler(id) {
            this.list = this.list.filter(item => item.id !== id)
        }
    },
    created() {
        // eslint-disable-next-line
        console.log('index created')
    },
    mounted() {
        // eslint-disable-next-line
        console.log('index mounted')
    },
    beforeUpdate() {
        // eslint-disable-next-line
        console.log('index before update')
    },
    updated() {
        // eslint-disable-next-line
        console.log('index updated')
    },
}
</script>

1.4.       2-7面试会考察哪些vue高级特性

1.4.1.    Vue 高级特性

·        面试

      不是每个都很常用,但用到的时候必须要知道

      考察候选人对 Vue 的掌握是否全面,且有深度

      考察做过的项目是否有深度和复杂度(至少能用到高级特性)

·        内容

      自定义 v-model

      $nextTick

      ref

      slot

      动态、异步组件

      keep-alive

      缓存的

      mixin

      重复逻辑

1.5.       2-8 vue如何自己实现v-model

1.5.1.    参考代码图片

·            

desc

·            

desc

·        参考代码

      <template>
    <!--
例如:vue 颜色选择 -->
    <!--
可理解为当输入的时候调用事件change1,并把事件的target.value传递回去 -->
    <input type="text"
        :value="text1"
        @input="$emit('change1', $event.target.value)"
    >
    <!--
        1.
上面的 input 使用了 :value 而不是 v-model
        2.
上面的 change1 model.event1 要对应起来
        3. text1
属性对应起来
    -->
</template>

<script>
export default {
    model: {
        prop: 'text1', //
对应 props text1
        event: 'change1'
    },
    //
接受v-model传递过来的属性
    props: {
        text1: String,
        default() {
            return ''
        }
    }
}
</script>

1.6.       2-9 vue组件更新之后如何获取最新DOM

1.6.1.    $nextTick

·        Vue 是异步渲染(原理部分会详细讲解)

·        data 改变之后,DOM 不会立刻渲染

·        $nextTick 会在 DOM 渲染之后被触发,以获取最新 DOM 节点

·        参考代码

      参考代码图片

         

desc

      参考代码

      <template>
  <div id="app">
    <ul ref="ul1">
        <li v-for="(item, index) in list" :key="index">
            {{item}}
        </li>
    </ul>
    <button @click="addItem">
添加一项</button>
  </div>
</template>

<script>
export default {
  name: 'app',
  data() {
      return {
        list: ['a', 'b', 'c']
      }
  },
  methods: {
    addItem() {
      //
这里是往列表中加入时间戳
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)
        this.list.push(`${Date.now()}`)

        // 1.
异步渲染,$nextTick DOM 渲染完再回调
        // 2.
页面渲染时会将 data 的修改做整合,多次 data 修改只会渲染一次
        // 3. $nextTick
会在 DOM 渲染之后被触发,以获取最新 DOM 节点
        this.$nextTick(() => {
          //
获取 DOM 元素
          const ulElem = this.$refs.ul1
          // eslint-disable-next-line
          // $nextTick
会在 DOM 渲染之后被触发,以获取最新 DOM 节点
          console.log( ulElem.childNodes.length ) 
        })
    }
  }
}
</script>





1.6.2.    ref

·        vue中拿到节点的元素

      参考代码图片

         

desc

1.7.       2-10 slot是什么

1.7.1.    基本使用

·        参考代码图片

      index.vue

         

desc

         

desc

      SlotDemo.vue

         

desc

      参考代码

      <template>
    <a :href="url">
        <slot>
           
默认内容,即父组件没设置内容时,这里显示
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {}
    }
}
</script>

·        slot的意义

      父组件往子组件中插入内容

1.7.2.    作用域插槽

·        参考代码图片

         

desc

      参考代码

      <template>
    <a :href="url">
        <!--
把子组件本地的data值传给父组件 -->
       <!-- 1.
绑定并自定义一个名slotData,然后对接子组件的data值对象website -->
        <slot :slotData="website">
            {{website.subTitle}} <!--
默认值显示 subTitle ,即父组件不传内容时 -->
        </slot>
    </a>
</template>

<script>
export default {
    props: ['url'],
    data() {
        return {
            website: {
                url: 'http://wangEditor.com/',
                title: 'wangEditor',
                subTitle: '
轻量级富文本编辑器'
            }
        }
    }
}
</script>

         

desc

1.7.3.    具名插槽

·        参考代码图片

         

desc

         

desc

·        就是有名字的插槽

1.8.       2-11 vue动态组件是什么

1.8.1.    :is=“component-name” 用法

1.8.2.    需要根据数据,动态渲染的场景。即组件类型不确定。

·        组件的变化,根据数据的变化来变化

1.8.3.    参考代码图片

·            

desc

·            

desc

1.9.       2-12 vue如何异步加载组件

1.9.1.    import() 函数

1.9.2.    按需加载,异步加载大组件

1.9.3.    参考代码图片

·            

desc

1.10.    2-13 vue如何缓存组件

1.10.1.  keep-alive

·        缓存组件

      一般情况下,v-if切换的时候会销毁原有的,重新渲染新的,但是用keep-alive包裹起来之后,就可以不用重复渲染了。有点类似v-show,但是v-show是通过样式来控制的。

      频繁切换组件,不需要重复渲染

      Vue常见性能优化方法之一

·        参考代码图片

         

desc

         

desc

      参考代码

      <template>
    <div>
        <button @click="changeState('A')">A</button>
        <button @click="changeState('B')">B</button>
        <button @click="changeState('C')">C</button>

        <!--
一般情况下,v-if切换的时候会销毁原有的,重新渲染新的。 v-show切换的时候修改样式,display:none -->
        <!-- tab
切换 -->
        <!-- keep-alive
包裹起来之后,就会 -->
        <keep-alive>
            <KeepAliveStageA v-if="state === 'A'"/>
            <KeepAliveStageB v-if="state === 'B'"/>
            <KeepAliveStageC v-if="state === 'C'"/>
        </keep-alive>
    </div>
</template>

<script>
import KeepAliveStageA from './KeepAliveStateA'
import KeepAliveStageB from './KeepAliveStateB'
import KeepAliveStageC from './KeepAliveStateC'

export default {
    components: {
        KeepAliveStageA,
        KeepAliveStageB,
        KeepAliveStageC
    },
    data() {
        return {
            state: 'A'
        }
    },
    methods: {
        changeState(state) {
            this.state = state
        }
    }
}
</script>

1.11.    2-14 vue组件如何抽离公共逻辑

1.11.1.  mixin

·        多个组件有相同的逻辑,抽离出来

·        mixin并不是完美的解决方案,会有一些问题

      变量来源不明确,不利于阅读

      多个mixin可能会造成命名冲突

      写完不一定会报错,还有可能覆盖了

      mixin和组件可能出现多对多的关系,复杂度较高

·        Vue3提出的composition API旨在解决这些问题

·        参考代码图片

         

desc

         

desc

      参考代码

      mixin.js

      export default {
    data() {
        return {
            city: '
北京'
        }
    },
    methods: {
        showName() {
            // eslint-disable-next-line
            console.log(this.name)
        }
    },
    mounted() {
        // eslint-disable-next-line
        console.log('mixin mounted', this.name)
    }
}

      MixinDemo.vue

      <template>
    <div>
        <p>{{name}} {{major}} {{city}}</p>
        <button @click="showName">
显示姓名</button>
    </div>
</template>

<script>
import myMixin from './mixin'

export default {
    mixins: [myMixin], //
可以添加多个,会自动合并起来
    data() {
        return {
            name: '
双越',
            major: 'web
前端'
        }
    },
    methods: {
    },
    mounted() {
        // eslint-disable-next-line
        console.log('component mounted', this.name)
    }
}
</script>

1.12.    2-15 vue高级特性知识点小结

1.12.1.  总结

·        自定义 v-model

·        $nextTick

·        refs

·        slot

·        动态、异步组件

·        keep-alive

      缓存的

·        mixin

      重复逻辑

1.12.2.  相关的面试技巧

·        可以不太深入,但必须知道

·        熟悉基本用法,了解使用场景

·        最好能和自己的项目经验结合起来

1.13.    2-16 vuex知识点串讲

1.13.1.  Vuex 使用

·        面试考点并不多(因为熟悉 Vue 之后,vuex 没有难度)

·        但基本概念、基本使用和 API 必须要掌握

·        可能会考察 state 的数据结构设计(后面会讲)

1.13.2.  Vuex 基本概念

·        state

·         getters

·        action

·        mutation

1.13.3.  用于 Vue 组件

·        dispatch

·        commit

·        mapState

·        mapGetters

·        mapActions

·        mapMutations

1.13.4.  参考图片

·            

desc

1.14.    2-17 vue-router知识点串讲

1.14.1.  Vue-router 使用

·        面试考点并不多(前提是熟悉 Vue

·        路由模式(hash H5 history

·        路由配置(动态路由、懒加载)

1.14.2.  Vue-router 路由模式

·        hash 模式(默认),如 http://abc.com/#/user/10

·        H5 history 模式,如 http://abc.com/user/20

      需要 server 端支持

      使用h5 history模式

      参考代码图片

         

desc

1.14.3.  Vue-router 路由配置 动态路由

·        参考代码图片

         

desc

1.14.4.  Vue-router 路由配置 懒加载

·        参考代码图片

         

desc

1.14.5.  总结

·        面试考点并不多(前提是熟悉 Vue

·        掌握基本概念,基本使用

·        面试官时间有限,需考察最核心、最常用的问题,而非边角问题

1.15.    2-18 vue使用-考点总结和复习

1.15.1.  Vue 使用总结

·        基本使用,组件使用

·        高级特性

·        Vuex Vue-router 使用

1.15.2.  回顾之前的 Vue 面试题

·        v-show v-if 的区别

      v-show是通过样式的display:none去控制的。v-if是根据vue本身的机制去控制,需要时才渲染。组件频繁切换的时候建议使用v-show,组件切换一次不频繁切换的时候用v-if

·        为何 v-for 中要用 key

      原理中有解释

·        描述 Vue 组件生命周期(有父子组件的情况)

·        Vue 组件如何通讯

      属性,触发事件

      父子组件,可以考虑

      自定义事件

      组件和组件之间没有关系,可以考虑

      vuex

      组件和组件之间没有关系,可以考虑

·        描述组件渲染和更新的过程

      原理中有解释

·        双向数据绑定 v-model 的实现原理

      原理中有解释

2.      Vue原理

2.1.       3-1 vue原理-大厂必考

2.1.1.    Vue 原理(大厂必考)

·        面试为何会考察原理?

·        面试中如何考察?以何种方式?

·        Vue 原理包括哪些?

2.1.2.    面试为何会考察原理,又用不到?

·        知其然而知其所以然 —— 各行业通用的道理

·        了解原理,才能应用的更好(竞争激烈,择优录取)

·        大厂造轮子(有钱有资源,业务定制,技术 KPI

2.1.3.    面试如何考察 Vue 原理?

·        考察重点,而不是考察细节。掌握好 2/8 原则

·        和使用相关联的原理,例如 vdom、模板渲染

·        整体流程是否全面?热门技术是否有深度?

2.1.4.    Vue 原理

·        组件化

·        响应式

·        vdom diff

·        模板编译

·        渲染过程

·        前端路由

2.2.       3-2如何理解MVVM

2.2.1.    组件化基础

·        很久以前就有组件化

      asp jsp php 已经有组件化了

      nodejs 中也有类似的组件化

·        数据驱动视图(MVVMsetState

      传统组件,只是静态渲染,更新还要依赖于操作 DOM

      根据数据来驱动视图

      数据驱动视图 – Vue MVVM

      数据驱动视图 – React setState(暂时按下不表)

      参考图片

         

desc

2.3.       3-3监听data变化的核心API是什么

2.3.1.    Vue 响应式

·        组件 data 的数据一旦变化,立刻触发视图的更新

·        实现数据驱动视图的第一步

·        考察 Vue 原理的第一题

·        核心 API - Object.defineProperty

      3.0之前用的这个

·        Object.defineProperty 的一些缺点(Vue3.0 启用 Proxy

2.3.2.    Proxy 有兼容性问题

·        Proxy 兼容性不好,且无法 polyfill

·        Vue2.x 还会存在一段时间,所以都得学

·        Vue3.0 相关知识,下一章讲,这里只是先提一下

2.3.3.    Object.defineProperty 基本用法

·        参考代码图片

         

desc

         

desc

2.3.4.    Object.defineProperty 实现响应式

·        监听对象,监听数组

·        复杂对象,深度监听

·        几个缺点

2.4.       3-4如何深度监听data变化

2.4.1.    Object.defineProperty 缺点

·        深度监听,需要递归到底,一次性计算量大

·        无法监听新增属性/删除属性

      所以使用Vue.set Vue.delete来代替

·        无法原生监听数组,需要特殊处理

2.5.       3-5 vue如何监听数组变化

2.5.1.    总结

·        基础 API – Object.defineProperty

·        如何监听对象(深度监听),监听数组

·        Object.defineProperty 的缺点

2.6.       3-6虚拟DOM-面试里的网红

2.6.1.    虚拟 DOMVirtual DOM)和 diff

·        vdom 是实现 vue React 的重要基石

·        diff 算法是 vdom 中最核心、最关键的部分

·        vdom 是一个热门话题,也是面试中的热门问题

2.6.2.    虚拟 DOMvdom)和 diff

·        DOM 操作非常耗费性能

·        以前用 jQuery ,可以自行控制 DOM 操作的时机,手动调整

·        Vue React 是数据驱动视图,如何有效控制 DOM 操作?

2.6.3.    解决方案 - vdom

·        有了一定复杂度,想减少计算次数比较难

·        能不能把计算,更多的转移为 JS 计算?因为 JS 执行速度很快

·        vdom - JS 模拟 DOM 结构,计算出最小的变更,操作 DOM

2.6.4.    JS 模拟 DOM 结构

·        参考代码图片

         

desc

         

desc

      标签

      属性

      子元素

2.6.5.    通过 snabbdom 学习 vdom

·        简洁强大的 vdom 库,易学易用

·        Vue 参考它实现的 vdom diff

·        https://github.com/snabbdom/snabbdom

·        Vue3.0 重写了 vdom 的代码,优化了性能

·        vdom 的基本理念不变,面试考点也不变

·        React vdom 具体实现和 Vue 也不同,但不妨碍统一学习

2.6.6.    总结

·        snabbdom 重点总结

      h 函数

      vnode 数据结构

      patch 函数

·        vdom 总结

      JS 模拟 DOM 结构(vnode

      新旧 vnode 对比,得出最小的更新范围,最后更新 DOM

      数据驱动视图的模式下,有效控制 DOM 操作

·        问题

      新旧 vnode 是如何比较的?

      传说中的 diff 算法是什么?

      patch 函数内部是如何实现的?

2.7.       3-7用过虚拟DOM

2.7.1.    同上

2.8.       3-8虚拟DOM-diff算法概述

2.8.1.    diff 算法

·        diff 算法是 vdom 中最核心、最关键的部分

·        diff 算法能在日常使用 vue React 中体现出来(如 key

·        diff 算法是前端热门话题,面试宠儿

2.8.2.    diff 算法概述

·        diff 即对比,是一个广泛的概念,如 linux diff 命令、git diff

·        两个 js 对象也可以做 diff ,如 https://github.com/cujojs/jiff

·        两棵树做 diff ,如这里的 vdom dif

·        参考图片

         

desc

2.8.3.    diff 的时间复杂度 O(n^3)

·        第一,遍历 tree1

·        第二,遍历 tree2

·        第三,排序

·        1000 个节点,要计算 1 亿次,算法不可用

2.8.4.    优化时间复杂度到 O(n)

·        只比较同一层级,不跨级比较

      参考图片

         

desc

·        tag 不相同,则直接删掉重建,不再深度比较

      参考图片

         

desc

·        tag key ,两者都相同,则认为是相同节点,不再深度比较

2.9.       3-9深入diff算法源码-生成vnode

2.10.    3-10深入diff算法源码-patch函数

2.11.    3-11深入diff算法源码-patchVnode函数

2.12.    3-12深入diff算法源码-updateChildren函数

2.13.    3-13虚拟DOM-考点总结和复习

2.14.    3-14模板编译前置知识点-with语法

2.15.    3-15 vue模板被编译成什么

2.16.    3-16 vue组件可用render代替template

2.17.    3-17回顾和复习已学的知识点

2.18.    3-18 vue组件是如何渲染和更新的

2.19.    3-19 vue组件是异步渲染的

2.20.    3-20如何用JS实现hash路由

2.21.    3-21如何用JS实现H5 history路由

2.22.    3-22 vue原理-考点总结和复习

3.      vue面试真题演练

4.      vue3面试题

4.1.       5-1 Proxy基本使用(1)

4.2.       5-2 Proxy基本使用(2)

4.3.       5-3 vue3Proxy实现响应式