Vue的响应式原理 双向数据绑定
- vue通过Object.defineProperty 劫持传进来的数据, 然后在数据getter的时候订阅重新编译模板的消息,然后通过js监听元素的事件,这里input事件也好,keyup事件也好,总是监听输入框值变化,将新的值重新赋值给被劫持的data,这样就会触发setter函数,再setter函数中就会去发布重新编译模板的消息;
- Model 改变 View的过程: 依赖于ES5的object.defindeProperty,通过 defineProperty 实现的数据劫持,getter 收集依赖,setter 调用更新回调(不同于观察者模式,是发布订阅 + 中介) View 改变 Model的过程: 依赖于 v-model ,该语法糖实现是在单向数据绑定的基础上,增加事件监听并赋值给对应的Model。
<input id="input" type="text" />
<div id="text"></div>
let input = document.getElementById("input");
let text = document.getElementById("text");
let data = { value: "" };
Object.defineProperty(data, "value", {
set: function(val) {
text.innerHTML = val;
input.value = val;
},
get: function() {
return input.value;
}
});
input.onkeyup = function(e) {
data.value = e.target.value;
};
vue组件的data属性为什么返回函数
- 对象是引用类型,当重用组件时,由于数据对象都指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改;
- 而使用函数返回对象的话,由于每次返回的都是一个新对象(Object的实例),引用地址不同,则不会出现这个问题。
vue3和vue2的区别
-
Vue2的双向数据绑定原理是通过 es5 的 Object.defineProperty, 中的 set 方法来实现数据劫持的,但是有一个弊端就是无法兼听到数组内部的数据变化(当 然我们可以通过 arr = arr.concat([])),来实现内部数据变化的检测。
Vue3.x 是用 ES6 的语法 Proxy对象来实现双向数据绑定的,可以检测到数组内部数据的变化。Proxy 用于修改某些操作的默认行为,也可以理解为
在目标对象之前架设一层拦截
,外部所有的访问都必须
先通过这层拦截
,因此提供了一种机制,可以对外部的访问进行过滤和修改。 -
Vue3.0 新加入了 TypeScript 以及 PWA 的支持
-
Vue2中把数据放入data属性中,方法放入methods中。
在Vue3.0,我们就需要使用一个新的合成型API,setup()方法,此方法在组件初始化构造的时候触发。创建声名方法其实和声名数据状态是一样的,先声名一个方法或者数据,然后在setup()方法中返回(return)。声明周期钩子函数也放在了setup()方法中。
vue的生命周期
- before create、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed
vue的通信方式
父子组件之间:
-
props和$emit
父组件通过v-bind绑定数据,子组件通过props接收父组件传过来的数据,利用
em
i
t
触发指定事件,父组件通过
emit触发指定事件,父组件通过
e
mi
t
触发指定事件,父组件通过
on监听子组件触发的对应事件 -
v-model
本质是v-bind和v-on的语法糖,在一个组件上使用v-model,默认会为组件绑定名为value的属性和名为input的事件。如下代码本质上是<input :value=“test” @input=“test = $event.target.value”>
-
.sync
.sync修饰符它的本质和v-model类似,它的本质也是v-bind和v-on的语法糖。当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。
-
pa
r
e
n
t
、
parent、
p
a
re
n
t
、
children和ref直接得到组件实例,可以实现父子组件、兄弟组件、跨级组件等数据通信
跨级组件通信
-
$attrs
将父组件直接传递给孙组件。儿子组件(Child.vue),中间层,作为父组件和孙子组件的传递中介,在儿子组件中给孙子组件添加v-bind=“$attrs”,这样孙子组件才能通过props接收到数据。
-
inheritAttrs
默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。
-
$listeners
上面讲了
at
t
r
s
是为了跨组件传递数据,那如果想通过孙子组件来给父组件传递数据呢?之前的做法也是一层一层的向上传递,比如用
attrs是为了跨组件传递数据,那如果想通过孙子组件来给父组件传递数据呢?之前的做法也是一层一层的向上传递,比如用
a
tt
rs
是为了跨组件传递数据,那如果想通过孙子组件来给父组件传递数据呢?之前的做法也是一层一层的向上传递,比如用
emit方法,但是子组件如果用不到,只是想改变父组件的数据,这时候我们就可以使用$listeners。 -
provide和inject
允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件嵌套的层次有多深,并在起上下游关系成立的时间里始终有效。一言以蔽之:
祖先组件中通过provider来提供变量,然后在子孙组件中通过inject来注入变量。
-
通过中央事件总线(Event Bus)
-
全局状态管理vuex