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>
响应式原则
-
Vue 内部会递归的去循环 vue 中的 data 属性,会给每个属性都增加 getter 和 setter,当属性值变化时会更新视图;
-
重写了数组中的方法 (push、pop、shift、unshift、sort、reverse、splice),当调用数组方法时会触发更新,也会对数组中的数据 (对象类型) 进行了监控;
-
通过以上两点可以发现 Vue 中的缺陷:
- 对象默认只监控自带的属性,新增的属性响应式不生效 (尽量少层级嵌套,层级过深,性能差);
- 数组通过索引进行修改 或者 修改数组的长度,响应式不生效;
-
vue2 性能优化:
- 对象层级过深,性能就会差,尽量少层级嵌套;
- 不需要响应数据的内容不要放到 data 中;
- Object.freeze() 可以冻结数据;
-
Vue 额外提供的 API 来解决缺陷:
// $set 不能给 vm 根实例添加属性 vm.$set(vm.arr, 0, 100); // 修改数组内部使用的是 splice 方法 vm.$set(vm.address, 'number', '6-301'); // 通过内部会将属性定义成响应式数据 vm.$delete(vm.arr, 0); // 删除索引,属性
-
为了解决以上问题,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 区别
-
传统的 MVC 指的是,用户操作会请求服务端路由,路由会调用对应的控制器来处理,控制器会获取数据,将结果返回给前端,页面重新渲染;
-
MVVM:传统的前端会将数据手动渲染到页面上,MVVM 模式不需要用户操作 dom 元素,通过 viewModel 层上的数据绑定和 dom 监听,会自动将数据渲染到页面中,视图变化会通知 viewModel 更新数据,viewModel 就是 MVVM 中的桥梁;
面试题
既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 dom 进行 diff 检测差异
响应式数据变化,vue 确实可以在数据发生变化时通过响应式系统立刻得知,但是如果给每个属性都添加 watcher 用于更新的话,会产生大量的 watcher 从而降低性能;
而且粒度过细也会导致更新不精确的问题,所以 vue 采用了组件级的 watcher 配合 diff 来检测差异;
Vue 中的性能优化有哪些?
数据层级不易过深,合理设置响应式数据;
使用数据时缓存值的结果,不频繁取值;
合理设置 key 属性:这有利于在列表变动时,尽量少的删除、新增、改动元素;
使用冻结的对象,冻结的对象不会被响应化;
v-show 和 v-if 的选取;
控制组件粒度 -> vue 采用组件级更新;
采用函数式组件 -> 函数式组件开销低;
采用异步组件 -> 借助 webpack 分包能力;
利用 requestAnimationFrame 延迟装载
采用 keep-alive 缓存组件;
虚拟滚动、时间分片等策略;
打包优化;
剑指 Offer 57 - II.和为s的连续正数序列
上一篇