Vue 中的模板

<script src="node_modules/vue/dist/vue.js"></script>
<!-- 3.外部模板 -->
<div id="app">{{name}}</div>
<script>
    const vm = new Vue({
        el: '#app',
        data: {
            name: 'jw',
            age: 22
        },
        // 2.内部模板
        template: '<div>{{age}}</div>',
        // 1.render函数
        render(h) {
            return h('h1', ['hello,', this.name, this.age])
        }
    });
    // 渲染流程:
    //  1.会先查找用户传入的 render
    //  2.如果没有传入 render 则查找 template 属性
    //  3.如果没有传入 template 则查找 el 属性,如果有 el,则采用 el 的模板
</script>

模板语法

<div id="app">
    <!-- 可以放入运算的结果 -->
    {{ 1+ 1 }}

    <!-- 当前这个表达式 最后会被编译成函数 _v(msg === 'hello'? true:false) -->
    {{ msg === 'hello'? true: false }}

    <!-- 取值操作,函数返回结果 -->
    {{ obj.a }} {{ fn() }}
</div>

响应式原则

  1. Vue 内部会递归的去循环 vue 中的 data 属性,会给每个属性都增加 gettersetter,当属性值变化时会更新视图;

  2. 重写了数组中的方法 (push、pop、shift、unshift、sort、reverse、splice),当调用数组方法时会触发更新,也会对数组中的数据 (对象类型) 进行了监控;

  3. 通过以上两点可以发现 Vue 中的缺陷:

    1. 对象默认只监控自带的属性,新增的属性响应式不生效 (尽量少层级嵌套,层级过深,性能差)
    2. 数组通过索引进行修改 或者 修改数组的长度,响应式不生效;
  4. vue2 性能优化:

    1. 对象层级过深,性能就会差,尽量少层级嵌套;
    2. 不需要响应数据的内容不要放到 data 中;
    3. Object.freeze() 可以冻结数据;
  5. Vue 额外提供的 API 来解决缺陷:

    // $set 不能给 vm 根实例添加属性
    vm.$set(vm.arr, 0, 100); // 修改数组内部使用的是 splice 方法 
    vm.$set(vm.address, 'number', '6-301'); // 通过内部会将属性定义成响应式数据        
    vm.$delete(vm.arr, 0);  // 删除索引,属性
    
  6. 为了解决以上问题,Vue3.x 使用 Proxy 来解决:

    // 代理 get、set 可以实现懒代理,并且兼容数组索引和长度变化
    let arr = ['吃', '喝', '玩'];
    
    let proxy = new Proxy(arr, {
      get(target, key) {
        return Reflect.get(target, key);
      },
      set(target, key, value) {
        let oldValue = target[key];
        if (!oldValue) {
          console.log('新增属性');
        } else if (oldValue !== value) {
          console.log('修改属性');
        }
        return Reflect.set(target, key, value);
      }
    });
    
    proxy[3] = '1';
    console.log(proxy); // ["吃", "喝", "玩", "1"]}
    proxy.length = 3;
    console.log(proxy); // [ '吃', '喝', '玩' ]
    

实例方法、属性

方法、属性 描述
vm._uid 每个实例的唯一标识
vm.$data === vm._data 实例的数据源
vm.$options 用户传入的属性
vm.$el 当前组件的真实 dom
vm.$nextTick 等待界面渲染完毕后,获取最新的 dom
vm.$mount 手动挂载实例
vm.$watch 监控数据变化

MVC 和 MVVM 区别

  1. 传统的 MVC 指的是,用户操作会请求服务端路由,路由会调用对应的控制器来处理,控制器会获取数据,将结果返回给前端,页面重新渲染;

  2. MVVM:传统的前端会将数据手动渲染到页面上,MVVM 模式不需要用户操作 dom 元素,通过 viewModel 层上的数据绑定和 dom 监听,会自动将数据渲染到页面中,视图变化会通知 viewModel 更新数据,viewModel 就是 MVVM 中的桥梁;

面试题

既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 dom 进行 diff 检测差异

  1. 响应式数据变化,vue 确实可以在数据发生变化时通过响应式系统立刻得知,但是如果给每个属性都添加 watcher 用于更新的话,会产生大量的 watcher 从而降低性能;

  2. 而且粒度过细也会导致更新不精确的问题,所以 vue 采用了组件级的 watcher 配合 diff 来检测差异;

Vue 中的性能优化有哪些?

  1. 数据层级不易过深,合理设置响应式数据;

  2. 使用数据时缓存值的结果,不频繁取值;

  3. 合理设置 key 属性:这有利于在列表变动时,尽量少的删除、新增、改动元素;

  4. 使用冻结的对象,冻结的对象不会被响应化;

  5. v-showv-if 的选取;

  6. 控制组件粒度 -> vue 采用组件级更新;

  7. 采用函数式组件 -> 函数式组件开销低;

  8. 采用异步组件 -> 借助 webpack 分包能力;

  9. 利用 requestAnimationFrame 延迟装载

  10. 采用 keep-alive 缓存组件;

  11. 虚拟滚动、时间分片等策略;

  12. 打包优化;

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. Vue 中的模板
  2. 2. 模板语法
  3. 3. 响应式原则
  4. 4. 实例方法、属性
  5. 5. MVC 和 MVVM 区别
  6. 6. 面试题
    1. 6.1. 既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 dom 进行 diff 检测差异
    2. 6.2. Vue 中的性能优化有哪些?