Vue双向数据绑定
vue是通过数据劫持和发布订阅者模式来实现双向数据绑定的 就是利用oberver来监听module数据的变化,通过compile来解析模板,最终通过watcher来建立oberver和module之间的通信桥梁 创建一个vue对象,分为el模板和data数据
- 使用Object.definePropertype来劫持data中的每个属性的getter和setter,在数据发生变化的时候发布消息给订阅者,触发相应的回调。(vue3使用proxy劫持数据)也就是observer的功能
- compile 解析模板,将模板中的变量替换成数据,然后动态渲染页面, 将双向绑定的指令对应的节点添加更新函数,添加监听数据的订阅者,一旦数据有变化,就更新视图
- Watcher订阅者是Observer和Compile之间通信的桥梁,他负责往dep里添加订阅者,当收到数据变化的通知时,触发compile的回调,更新视图
(vue中就是每当有这样的可能用到双向绑定的指令,就在一个Dep中增加一个订阅者)
使用 Object.defineProperty() 来进行数据劫持有什么缺点?
使用Object.defineProperty() 拦截不了一些变化,比如通过下标的形式修改数组或者给对象添加新属性,都是不能拦截的,只是Vue内部重写了函数才解决了这个问题 所以vue3利用proxy代理器来进行数据劫持
<body>
name: <span id="spanName"></span>
<br>
<input type="text" id="inputName">
</body>
<script>
var span = document.getElementById('spanName')
var input = document.getElementById('inputName')
var obj = {
name: ''
}
使用proxy数据劫持
obj = new Proxy(obj, {
get(target, prop) {
return target[prop]
},
set(target, prop, value) {
target[prop] = value
observer() //当数据有更新,改变页面的内容
}
})
function observer() {
span.innerHTML = obj.name
input.value = obj.name
}
input.oninput = function () {
obj.name = input.value //页面上的输入有变化,改变obj的数据
}
</script>
MVC、MVVM区别
MVC(单向数据改变) MVC 通过分离 Model、View 和 Controller 的方式来组织代码结构。Model是负责存储页面的数据,View是负责页面的显示功能,Controller是处理用户交互的部分(数据的改变引起视图的改变)可以使用onchange来改变数据 MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。 MVVM(双向数据改变) ViewModel负责监听Model中数据的改变并且控制视图的更新,处理用户交互操作; Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系,因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。
Computed 和 Watch 的区别
- computed 计算属性 : 依赖其它属性值,并且 computed 的值有缓存,只有它依赖的值发生改变时,下一次获取 computed 的值时才会重新计算 computed 的值。
- watch 侦听器 : 更多的是观察的作用,无缓存性,类似于某些数据的监听回调,每当监听的数据变化时都会执行回调进行后续操作。
运用场景: 当需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时都要重新计算。 当需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许执行异步操作 ( 访问一个 API ),限制执行该操作的频率,并在得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
Computed 和 Methods 的区别
可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的 不同点: computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值; method 调用总会执行该函数。
slot是什么?有什么作用?原理是什么?
slot又分三类,默认插槽,具名插槽和作用域插槽 组件的插槽也是为了让我们封装的组件更加具有扩展性。 让使用者可以决定组件内部的一些内容到底展示什么。 比如:导航栏组件,可以在里面做插槽,然后使用的时候按照需要来替换插槽 匿名插槽:又名匿名插槽,当slot没有指定name属性值的时候一个默认显示插槽,一个组件内只显示一个匿名插槽。 也就是带有name属性的slot,一个组件可以出现多个具名插槽。 具名插槽:带有name的插槽,一个组件可以有多个具名插槽,父级组件通过对应的slot属性来对应子组件的插槽的name来替换 作用域插槽:父组件替换插槽的标签,但是内容由子组件来提供。该插槽的不同点是在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件的传递过来的数据决定如何渲染该插槽。 在父组件使用我们的子组件时,从子组件中拿到数据:我们通过获取到slotProps属性 在通过slotProps.data就可以获取到刚才我们传入的data了
过滤器的作用,如何实现一个过滤器
filters不会修改数据,而是过滤数据,改变用户看到的输出 使用场景: 需要格式化数据的情况,比如需要处理时间、价格等数据格式的输出格式。 过滤器是一个函数,它会把表达式中的值始终当作函数的第一个参数。
如何保存页面的当前的状态
在Vue中,还可以是用keep-alive来缓存页面,当组件在keep-alive内被切换时组件的activated、deactivated这两个生命周期钩子函数会被执行 被包裹在keep-alive中的组件的状态将会被保留:
常见的事件修饰符及其作用
- .once : 该事件指触发一次
- .stop :放置事件冒泡,相当于原生中的event.stopPropagation()
- .prevent :取消默认事件,比如阻止表单提交等同于 JavaScript 中的 event.preventDefault()
- .native - 监听组件根元素的原生事件
- .capture :与事件冒泡的方向相反,事件捕获由外到内;
v-if和v-show的区别
- v-if是动态的向DOM树中添加或删除元素,而v-show是改变元素的diaplay属性
- v-if时惰性的,当第一次的条件时false,就什么都不做,只有在首次条件为true时,才做局部编译;而v-show无论初始条件是什么都会被编译
v-html,v-once,v-pre, v-cloak
v-html会先移除节点下的所有节点,将字符串解析成html标签,就是将innerHTML值设置为解析好的标签 v-once组件只会渲染一次,之后里面的数据变化他也不会变化 v-pre用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache语法。 v-cloak: 可以用v-cloak来设置浏览器没有编译完成时组件的样式
|