Skip to content

Commit cfbbcec

Browse files
pikaxantfu
andauthored
feat(shallowReadonly): add shallowReadonly and set computed to be shallowReadonly (#447)
* feat(shallowReadonly): add shallowReadonly and set computed to be shallowReadonly * chore: fix tests * chore: readme * chore:restore formatting * docs: update zh-CN README Co-authored-by: Anthony Fu <[email protected]>
1 parent 4284f61 commit cfbbcec

File tree

11 files changed

+562
-79
lines changed

11 files changed

+562
-79
lines changed

README.md

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,15 @@ import { ref, reactive } from '@vue/composition-api'
3838
Include `@vue/composition-api` after Vue and it will install itself automatically.
3939

4040
<!--cdn-links-start-->
41+
4142
```html
4243
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
4344
<script src="https://cdn.jsdelivr.net/npm/@vue/[email protected]"></script>
4445
```
46+
4547
<!--cdn-links-end-->
4648

47-
`@vue/composition-api` will be exposed to global variable `window.VueCompositionAPI`.
49+
`@vue/composition-api` will be exposed to global variable `window.VueCompositionAPI`.
4850

4951
```ts
5052
const { ref, reactive } = VueCompositionAPI
@@ -68,8 +70,6 @@ export default defineComponent({
6870

6971
To make JSX/TSX work with `@vue/composition-api`, check out [babel-preset-vca-jsx](https://github.com/luwanquan/babel-preset-vca-jsx) by [@luwanquan](https://github.com/luwanquan).
7072

71-
72-
7373
## SSR
7474

7575
Even if there is no definitive Vue 3 API for SSR yet, this plugin implements the `onServerPrefetch` lifecycle hook that allows you to use the `serverPrefetch` hook found in the classic API.
@@ -78,7 +78,7 @@ Even if there is no definitive Vue 3 API for SSR yet, this plugin implements the
7878
import { onServerPrefetch } from '@vue/composition-api'
7979

8080
export default {
81-
setup (props, { ssrContext }) {
81+
setup(props, { ssrContext }) {
8282
const result = ref()
8383

8484
onServerPrefetch(async () => {
@@ -88,8 +88,8 @@ export default {
8888
return {
8989
result,
9090
}
91-
},
92-
};
91+
}
92+
}
9393
```
9494

9595
## Limitations
@@ -124,7 +124,6 @@ state.list[1].value === 1 // true
124124
❌ <b>Should NOT</b> use <code>ref</code> in a plain object when working with <code>Array</code>
125125
</summary>
126126

127-
128127
```js
129128
const a = {
130129
count: ref(0),
@@ -162,8 +161,8 @@ const a = reactive({
162161
list: [
163162
reactive({
164163
count: ref(0),
165-
})
166-
],
164+
}),
165+
]
167166
})
168167
// unwrapped
169168
a.list[0].count === 0 // true
@@ -179,7 +178,6 @@ a.list[1].count === 1 // true
179178

180179
</details>
181180

182-
183181
### Template Refs
184182

185183
<details>
@@ -212,7 +210,6 @@ a.list[1].count === 1 // true
212210

213211
</details>
214212

215-
216213
<details>
217214
<summary>
218215
✅ String ref && return it from <code>setup()</code> && Render Function / JSX
@@ -238,8 +235,8 @@ export default {
238235
},
239236
}
240237
```
241-
</details>
242238

239+
</details>
243240

244241
<details>
245242
<summary>
@@ -266,7 +263,6 @@ export default {
266263

267264
</details>
268265

269-
270266
<details>
271267
<summary>
272268
❌ Render Function / JSX in <code>setup()</code>
@@ -301,7 +297,6 @@ export default {
301297
302298
If you really want to use template refs in this case, you can access `vm.$refs` via `SetupContext.refs`
303299

304-
305300
```jsx
306301
export default {
307302
setup(initProps, setupContext) {
@@ -347,7 +342,6 @@ declare module '@vue/composition-api' {
347342

348343
> :bulb: In Vue 3, it will return an new proxy object.
349344
350-
351345
</details>
352346

353347
### Watch
@@ -359,11 +353,11 @@ declare module '@vue/composition-api' {
359353

360354
```js
361355
watch(() => {
362-
/* ... */
356+
/* ... */
363357
}, {
364358
immediate: true,
365-
onTrack() {}, // not available
366-
onTrigger() {}, // not available
359+
onTrack() {}, // not available
360+
onTrigger() {}, // not available
367361
})
368362
```
369363

@@ -389,18 +383,26 @@ app2.component('Bar', Bar) // equivalent to Vue.use('Bar', Bar)
389383

390384
</details>
391385

386+
### shallowReadonly
387+
388+
<details>
389+
<summary>
390+
⚠️ <code>shallowReadonly()</code> will create a new object and with the same root properties, new properties added will <b>not</b> be readonly or reactive.
391+
</summary>
392+
393+
> :bulb: In Vue 3, it will return an new proxy object.
394+
395+
</details>
392396

393397
### Missing APIs
394398

395399
The following APIs introduced in Vue 3 are not available in this plugin.
396400

397401
- `readonly`
398-
- `shallowReadonly`
399402
- `defineAsyncComponent`
400403
- `onRenderTracked`
401404
- `onRenderTriggered`
402405
- `isProxy`
403-
- `isReadonly`
404406
- `isVNode`
405407

406408
### Reactive APIs in `data()`
@@ -415,18 +417,16 @@ export default {
415417
data() {
416418
return {
417419
// will result { a: { value: 1 } } in template
418-
a: ref(1)
420+
a: ref(1),
419421
}
420422
},
421423
}
422424
```
423425

424426
</details>
425427

426-
427428
### Performance Impact
428429

429430
Due the the limitation of Vue2's public API. `@vue/composition-api` inevitably introduced some extract costs. It shouldn't bother you unless in extreme environments.
430431

431432
You can check the [benchmark results](https://antfu.github.io/vue-composition-api-benchmark-results/) for more details.
432-

README.zh-CN.md

Lines changed: 41 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,17 @@ export default defineComponent({
7878
import { onServerPrefetch } from '@vue/composition-api'
7979

8080
export default {
81-
setup (props, { ssrContext }) {
81+
setup(props, { ssrContext }) {
8282
const result = ref()
8383

8484
onServerPrefetch(async () => {
8585
result.value = await callApi(ssrContext.someId)
8686
})
8787

8888
return {
89-
result,
89+
result
9090
}
91-
},
91+
}
9292
}
9393
```
9494

@@ -130,27 +130,27 @@ state.list[1].value === 1 // true
130130

131131
```js
132132
const a = {
133-
count: ref(0),
133+
count: ref(0)
134134
}
135135
const b = reactive({
136-
list: [a], // `a.count` 不会自动展开!!
136+
list: [a] // `a.count` 不会自动展开!!
137137
})
138138

139139
// `count` 不会自动展开, 须使用 `.value`
140-
b.list[0].count.value === 0; // true
140+
b.list[0].count.value === 0 // true
141141
```
142142

143143
```js
144144
const b = reactive({
145145
list: [
146146
{
147-
count: ref(0), // 不会自动展开!!
148-
},
149-
],
147+
count: ref(0) // 不会自动展开!!
148+
}
149+
]
150150
})
151151

152152
// `count` 不会自动展开, 须使用 `.value`
153-
b.list[0].count.value === 0; // true
153+
b.list[0].count.value === 0 // true
154154
```
155155

156156
</details>
@@ -163,17 +163,17 @@ b.list[0].count.value === 0; // true
163163

164164
```js
165165
const a = reactive({
166-
count: ref(0),
166+
count: ref(0)
167167
})
168168
const b = reactive({
169-
list: [a],
169+
list: [a]
170170
})
171171
// 自动展开
172172
b.list[0].count === 0 // true
173173

174174
b.list.push(
175175
reactive({
176-
count: ref(1),
176+
count: ref(1)
177177
})
178178
)
179179
// 自动展开
@@ -205,9 +205,9 @@ b.list[1].count === 1; // true
205205
})
206206
207207
return {
208-
root,
208+
root
209209
}
210-
},
210+
}
211211
}
212212
</script>
213213
```
@@ -232,13 +232,13 @@ export default {
232232
})
233233

234234
return {
235-
root,
235+
root
236236
}
237237
},
238238
render() {
239239
// 使用 JSX
240240
return () => <div ref="root" />
241-
},
241+
}
242242
}
243243
```
244244

@@ -262,9 +262,9 @@ export default {
262262
const root = ref(null)
263263
264264
return {
265-
root,
265+
root
266266
}
267-
},
267+
}
268268
}
269269
</script>
270270
```
@@ -289,7 +289,7 @@ export default {
289289

290290
// 使用 JSX
291291
return () => <div ref={root} />
292-
},
292+
}
293293
}
294294
```
295295

@@ -348,7 +348,7 @@ declare module '@vue/composition-api' {
348348

349349
此行为与 Vue 2 中的 `Vue.observable` 一致
350350

351-
> :bulb: 在 Vue 3 中,`reactive()` 会返回一个新的的代理对象.
351+
> :bulb: 在 Vue 3 中,`reactive()` 会返回一个新的的代理对象
352352
353353
</details>
354354

@@ -361,33 +361,42 @@ declare module '@vue/composition-api' {
361361
</summary>
362362

363363
```js
364-
watch(() => {
365-
/* ... */
366-
}, {
367-
immediate: true,
368-
onTrack() {}, // 不可用
369-
onTrigger() {}, // 不可用
370-
})
364+
watch(
365+
() => {
366+
/* ... */
367+
}, {
368+
immediate: true,
369+
onTrack() {}, // 不可用
370+
onTrigger() {}, // 不可用
371+
}
372+
)
371373
```
372374

373375
</details>
374376

377+
### shallowReadonly
378+
379+
<details>
380+
<summary>
381+
⚠️ <code>shallowReadonly()</code> 会返回一个新的浅拷贝对象,在此之后新加的字段<b>将不会</b>获得只读或响应式状态。
382+
</summary>
383+
384+
> :bulb: 在 Vue 3 中,`shallowReadonly()` 会返回一个新的的代理对象
385+
386+
</details>
375387

376388
### 缺失的 API
377389

378390
以下在 Vue 3 新引入的 API ,在本插件中暂不适用:
379391

380392
- `readonly`
381-
- `shallowReadonly`
382393
- `defineAsyncComponent`
383394
- `onRenderTracked`
384395
- `onRenderTriggered`
385396
- `customRef`
386397
- `isProxy`
387-
- `isReadonly`
388398
- `isVNode`
389399

390-
391400
### `data()` 中使用组合式 API
392401

393402
<details>
@@ -402,7 +411,7 @@ export default {
402411
// 在模版中会成为 { a: { value: 1 } }
403412
a: ref(1)
404413
}
405-
},
414+
}
406415
}
407416
```
408417

0 commit comments

Comments
 (0)