You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+36-8
Original file line number
Diff line number
Diff line change
@@ -4,9 +4,17 @@
4
4
5
5
An abstracted util factory for creating **scoped**, **declarative**, and **reactive** context-components in Vue. This API abstraction is greatly inspired by [`React.createContext`](https://reactjs.org/docs/context.html) using Vue's [`prvide/inject` API](https://vuejs.org/v2/api/#provide-inject) under the hood. The usage and its behaviour is exactly the same as you may expect if you already familiar with React. With this library to power up your Vue application, you then now able to use `prvide/inject` in an explicit, but declarative manner for managing application contexts using component composition. It's just that easy.
6
6
7
+
## ✨ Highlights
8
+
9
+
- Solve **prop-drilling** without the full state management solution; good for library development.
10
+
- Declarative, reusable, but explicit, you know where your data came from and how to access it.
11
+
- Easier to debug, just search `Context.Provider` in the devTool then you know where data get injected.
12
+
- Free from name clash, there are just no chance to mess up `provide/inject`. Zero overhead!
13
+
- Seamless developing experiences for people came from React.
14
+
7
15
## 🧰 Requirements
8
16
9
-
This library recommend to have Vue 2.6+, where Vue introduces the `v-slot` derivative, opening a clean declarative pattern for passing component props in a compositional manner.
17
+
This library recommend to have Vue 2.6+, so we can leverage the `v-slot` derivative to write readable code.
10
18
11
19
## 🎬 Getting started
12
20
@@ -18,11 +26,14 @@ yarn add vue-create-context
18
26
19
27
## 📔 API
20
28
29
+
It is recommended to read [React context doc](https://reactjs.org/docs/context.html) to have a better idea on the API design. The doc here will just focus on the usage and the difference in Vue.
Calling `createContext` with the `defaultValue` to create a context object. The `defaultValue` can be either a referential object or primitive, which is **ONLY** used when the `Consumer` component can not find its conjugated `Provider` above the rendering tree.
@@ -41,18 +52,34 @@ Note: If the provided value is reactive, update this value "reactively" will als
41
52
42
53
```vue
43
54
<MyContext.Consumer v-slot="/* slot props: the value injected by the closed Provider */">
44
-
/* you can access the value within the block */
45
-
/* note: as a normal renderless component, this block have no access to computed properties */
55
+
<!-- you can access the value within the block -->
46
56
</MyContext.Consumer>
47
57
```
48
58
49
-
The `Consumer` gives the access to the injected value from the closest `Provider`. Unlike React, where uses the CAAF (children as a function, also known as the "render prop") pattern to access the value, we uses `v-slot` inside the component block template to access the value (the so called "slot props"). If you uses single file component (SFC) or browsers supports ES6+ object spread operator, you can take the advantage of object destructuring (see more on [Vue's official documentation](https://vuejs.org/v2/guide/components-slots.html#Destructuring-Slot-Props)).
59
+
The `Consumer`is a _functional_ component gives the access to the injected value from the closest `Provider`. Unlike React, where uses the CAAF (children as a function, also known as the "render prop") pattern to access the value, we uses `v-slot` inside the component block template to access the value (the so called "slot props"). If you uses single file component (SFC) or browsers supports ES6+ object spread operator, you can take the advantage of object destructuring (see more on [Vue's official documentation](https://vuejs.org/v2/guide/components-slots.html#Destructuring-Slot-Props)).
50
60
51
-
It is worth to mention that due to the current implementation of Vue's scoped slot API, the slot props have to be an object, so it is recommended to give the value as an plan old javascript object (POJO). In the case of the provided value to be a primitive, it will be normalized as an object with a `value`key to get the passed value in `v-slot`, i.e. `{ value: /* your provided value */ }`.
61
+
It is worth to mention that due to the current implementation of Vue's scoped slot API, the slot props have to be an object, so it is recommended to give the value as an plan old javascript object (POJO). In the case of the provided value to be a primitive, it will be normalized as an object with a `value`property to get the passed value in `v-slot`, i.e. `{ value: /* your provided value */ }`.
52
62
53
63
Note: You might be tempted to mutate the injected value from the consumer block. This is generally a bad idea since it violate the principle of "[props down, event up](https://vuejs.org/v2/style-guide/#Implicit-parent-child-communication-use-with-caution)"; therefore, it is recommend to treat the slot props as read only properties. Under the hood, this reactivity behaviour of slot props is just a reflection of the `provide/inject` API.
54
64
55
-
⚠️ **Caveat**: After chat with Vue's core team member @linusborg in Discord, the current constrain limits the template inside `Consumer` block have no access to the computed properties, but it can access to state value defined in `data` though. Please use it with caution!
65
+
### `Context._context`
66
+
67
+
Internally, calling `createContext` will generate an unique identifier as a key to access the inject value at runtime, that is why there are no such chance to have clashes. But if you need the injected value to be used in `computed` property, then you manually have to setup `inject` property on the component instance (thanks to Vue's core team member @linusborg for pointing out this). For such usage, you can bind the injected context as the following:
68
+
69
+
```js
70
+
{
71
+
inject: {
72
+
[name]:MyContext._context,
73
+
},
74
+
computed: {
75
+
[something]() {
76
+
returnthis[name]() // please note 'this[name]' is a accessor function with reactivity.
77
+
},
78
+
},
79
+
}
80
+
```
81
+
82
+
Node: the bound property is a **function** that returns the injected value, which follows the same rule as in `Consumer`. You can still expect to receive the `defaultValue` in case have no `Provider` being traced.
56
83
57
84
## 💎 Example
58
85
@@ -64,6 +91,7 @@ For people using the SFC format, here is an conceptual example.
0 commit comments