封装Vue组件的原则及技巧
根据组件单向数据流和和事件通信机制,需要由子组件通过事件通知父组件,并在父组件中修改原始的prop数据,完成状态的更新,(如购物车的商品数量counter组件)。在子组件中修改父组件的数据的场景在业务中也是比较常见的,那么有什么办法可以“绕开”单向数据流的限制呢?
v-model 解决
可以拆解为 props: value 和 events: input
像v-model的这种,用提供了手动挂载的方法$mount
本文整理了几种实现Vue组件的技巧
- 以counter计数器组件为例,展示了通过v-model语法糖同步父子组件的方式
- 以表单验证组件为例,展示了通过获取子组件的实例来封装组件的方法
- 以全局弹窗组件为例,展示了手动mount挂载组件封装API组件的方式
- 以throttle节流组件为例,展示了在vue中一种实现高阶组件的方式
Vue父子组件生命周期执行顺序是什么?
流程问题
Figure 27. Previewing the timing breakdown of a request
#Timing breakdown phases explained
Here's more information about each of the phases you may see in the Timing tab:
-
Queueing. The browser queues requests when:
- There are higher priority requests.
- There are already six TCP connections open for this origin, which is the limit. Applies to HTTP/1.0 and HTTP/1.1 only.
- The browser is briefly allocating space in the disk cache
-
Stalled. The request could be stalled for any of the reasons described in Queueing.
-
DNS Lookup. The browser is resolving the request's IP address.
-
Initial connection. The browser is establishing a connection, including TCP handshakes/retries and negotiating an SSL.
-
Proxy negotiation. The browser is negotiating the request with a proxy server.
-
Request sent. The request is being sent.
-
ServiceWorker Preparation. The browser is starting up the service worker.
-
Request to ServiceWorker. The request is being sent to the service worker.
-
Waiting (TTFB) . The browser is waiting for the first byte of a response. TTFB stands for Time To First Byte. This timing includes 1 round trip of latency and the time the server took to prepare the response.
-
Content Download. The browser is receiving the response, either directly from the network or from a service worker. This value is the total amount of time spent reading the response body. Larger than expected values could indicate a slow network, or that the browser is busy performing other work which delays the response from being read.
-
Receiving Push. The browser is receiving data for this response via HTTP/2 Server Push.
-
Reading Push. The browser is reading the local data previously received.
通信问题
vue中组件之间的通信方式?
父子组件
- 父子props去传
- 子父通过$emit派发自定义事件
- 在子代通过$parent去访问老爹
- 老爹中通过ref去访问孩子(存在暴露子组件问题,要注意用的场景)
- 爷孙透传$attrs
兄弟组件
- 采用桥接模式:root,手写eventbus
- vuex
跨层级的关系
- eventbus
- vuex
- provide+inject
vue被废除的组件
- 在 3.x 中,refs
- off 和 $once 实例方法已被移除,组件实例不再实现事件触发接口,如eventbus。我们可以替换成外部使用,例如 mitt 或 tiny-emitter
在绝大多数情况下,不鼓励使用全局的事件总线在组件之间进行通信。虽然在短期内往往是最简单的解决方案,但从长期来看,它维护起来总是令人头疼。根据具体情况来看,有多种事件总线的替代方案:
- Prop 和事件应该是父子组件之间沟通的首选。兄弟节点可以通过它们的父节点通信。
- Provide 和 inject 允许一个组件与它的插槽内容进行通信。这对于总是一起使用的紧密耦合的组件非常有用。
provide/inject也能够用于组件之间的远距离通信。它可以帮助避免“prop 逐级透传”,即 prop 需要通过许多层级的组件传递下去,但这些组件本身可能并不需要那些 prop。- Prop 逐级透传也可以通过重构以使用插槽来避免。如果一个中间组件不需要某些 prop,那么表明它可能存在关注点分离的问题。在该类组件中使用 slot 可以允许父节点直接为它创建内容,因此 prop 可以被直接传递而不需要中间组件的参与。
- 全局状态管理,比如 Vuex。
Provide / Inject
为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 或 reactive。
provide/inject实现原理总结
通过上面的分析,可以得知provide/inject实现原理还是比较简单的,就是巧妙地利用了原型和原型链进行数据的继承和获取。provide API调用设置的时候,设置父级的provides为当前provides对象原型对象上的属性,在inject获取provides对象中的属性值时,优先获取provides对象自身的属性,如果自身查找不到,则沿着原型链向上一个对象中去查找。
拓展:Object.create原理
Object.myCreate = function (proto, propertyObject = undefined) {
if (propertyObject === null) {
// 这里没有判断propertyObject是否是原始包装对象
throw 'TypeError'
} else {
function Fn () {}
// 设置原型对象属性
Fn.prototype = proto
const obj = new Fn()
if (propertyObject !== undefined) {
Object.defineProperties(obj, propertyObject)
}
if (proto === null) {
// 创建一个没有原型对象的对象,Object.create(null)
obj.__proto__ = null
}
return obj
}
}