Skip to content

Commit 335c9c6

Browse files
skirtles-codenaokie
authored andcommitted
docs: add the expose option and expose function (#1251)
1 parent d00391d commit 335c9c6

File tree

5 files changed

+127
-14
lines changed

5 files changed

+127
-14
lines changed

src/api/composition-api.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ A component option that is executed **before** the component is created, once th
4141
attrs: Data
4242
slots: Slots
4343
emit: (event: string, ...args: unknown[]) => void
44+
expose: (exposed?: Record<string, any>) => void
4445
}
4546

4647
function setup(props: Data, context: SetupContext): Data
@@ -89,12 +90,37 @@ A component option that is executed **before** the component is created, once th
8990
setup() {
9091
const readersNumber = ref(0)
9192
const book = reactive({ title: 'Vue 3 Guide' })
92-
// Please note that we need to explicitly expose ref value here
93+
// Please note that we need to explicitly use ref value here
9394
return () => h('div', [readersNumber.value, book.title])
9495
}
9596
}
9697
```
9798

99+
If you return a render function then you can't return any other properties. If you need to expose properties so that they can be accessed externally, e.g. via a `ref` in the parent, you can use `expose`:
100+
101+
```js
102+
// MyBook.vue
103+
104+
import { h } from 'vue'
105+
106+
export default {
107+
setup(props, { expose }) {
108+
const reset = () => {
109+
// Some reset logic
110+
}
111+
112+
// If you need to expose multiple properties they must all
113+
// be included in the object passed to expose. expose can
114+
// only be called once.
115+
expose({
116+
reset
117+
})
118+
119+
return () => h('div')
120+
}
121+
}
122+
```
123+
98124
- **See also**: [Composition API `setup`](../guide/composition-api-setup.html)
99125

100126
## Lifecycle Hooks

src/api/options-composition.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -286,26 +286,29 @@
286286
},
287287
setup({ name }) {
288288
watchEffect(() => {
289-
console.log(`name is: ` + name) // Will not be reactive!
289+
console.log(`name is: ` + name) // リアクティブではないでしょう!
290290
})
291291
}
292292
}
293293
```
294294

295295
`props` オブジェクトは、開発中のユーザランドのコードにとってはイミュータブルです(ユーザのコードがそれを変更しようとすると警告を表示します)。
296296

297-
第 2 引数は、`this` で以前に公開されていたプロパティの選択的な一覧を公開するコンテキストオブジェクトを提供します:
297+
第 2 引数は、`setup` で便利だと思われる様々なオブジェクトや関数を公開するコンテキストオブジェクトを提供します:
298298

299299
```js
300300
const MyComponent = {
301301
setup(props, context) {
302302
context.attrs
303303
context.slots
304304
context.emit
305+
context.expose
305306
}
306307
}
307308
```
308309

310+
`attrs``slots``emit` はそれぞれ、インスタンスプロパティの [`$attrs`](/api/instance-properties.html#attrs)[`$slots`](/api/instance-properties.html#slots)[`$emit`](/api/instance-methods.html#emit) と同じです。
311+
309312
`attrs``slots` は内部コンポーネントインスタンスの対応する値へのプロキシです。これは更新後も常に最新の値が公開されることを保証するので、古くなった参照へのアクセスを心配することなく、構造を変更することができます:
310313

311314
```js
@@ -319,6 +322,26 @@
319322
}
320323
```
321324

325+
Vue 3.2 で追加された `expose` は、特定のプロパティをパブリックなコンポーネントインスタンスを介して公開することができる関数です。デフォルトでは、refs や `$parent``$root` を使って取得したパブリックなインスタンスは、テンプレートが使う内部インスタンスと同じです。`expose` を呼び出すと、指定したプロパティを持つ別のパブリックなインスタンスが作成されます:
326+
327+
```js
328+
const MyComponent = {
329+
setup(props, { expose }) {
330+
const count = ref(0)
331+
const reset = () => count.value = 0
332+
const increment = () => count.value++
333+
334+
// reset だけが、例えば $refs を介して、外部から利用できるようになります
335+
expose({
336+
reset
337+
})
338+
339+
// 内部的には、テンプレートは count と increment にアクセスできます
340+
return { count, increment }
341+
}
342+
}
343+
```
344+
322345
`props` がコンテキストに含まれる代わりに、別の第 1 引数として置かれている理由はいくつかあります:
323346

324347
- コンポーネントが `props` を使うことが、他のプロパティよりもずっと一般的であること、そしてコンポーネントが `props` のみを扱うことがとても頻繁にあることです。

src/api/options-data.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,6 @@
252252
_ウォッチャの定義にアロー関数を使ってはいけない_ ということに注意してください(例: `searchQuery: newValue => this.updateAutocomplete(newValue)`)。その理由は、アロー関数が親のコンテキストを束縛するため、`this` は期待したとおりのコンポーネントインスタンスにはならないのと、`this.updateAutocomplete` が未定義になるからです。
253253
:::
254254

255-
256255
- **参照:** [ウォッチャ](../guide/computed.html#ウォッチャ)
257256

258257
## emits
@@ -302,3 +301,39 @@
302301
:::
303302

304303
* **参照:** [属性の継承](../guide/component-attrs.html#属性の継承)
304+
305+
## expose <Badge text="3.2+" />
306+
307+
- **型:** `Array<string>`
308+
309+
- **詳細:**
310+
311+
パブリックなコンポーネントインスタンスで公開するプロパティのリストです。
312+
313+
デフォルトでは、[`$refs`](/api/instance-properties.html#refs)[`$parent`](/api/instance-properties.html#parent)[`$root`](/api/instance-properties.html#root) からアクセスされるパブリックなインスタンスは、テンプレートで使われる内部コンポーネントのインスタンスと同じです。`expose` オプションは、パブリックなインスタンスからアクセス可能なプロパティを制限します。
314+
315+
Vue 自身が定義した `$el``$parent` などのプロパティは、常にパブリックなインスタンスで利用可能で、このリストに加える必要はありません。
316+
317+
- **使用方法:**
318+
319+
```js
320+
export default {
321+
// increment は公開されますが、
322+
// count は内部的にしかアクセスできません
323+
expose: ['increment'],
324+
325+
data() {
326+
return {
327+
count: 0
328+
}
329+
},
330+
331+
methods: {
332+
increment() {
333+
this.count++
334+
}
335+
}
336+
}
337+
```
338+
339+
- **参照:** [defineExpose](/api/sfc-script-setup.html#defineexpose)

src/guide/composition-api-setup.md

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> このセクションではコード例に[単一ファイルコンポーネント](single-file-component.html)の構文を使います。
44
5-
> このガイドは[Composition API の導入](composition-api-introduction.html)[リアクティブの基礎](reactivity-fundamentals.html)を既に読んでいることを想定しています。 Composition API に初めて触れる方は、まずそちらを読んでみてください。
5+
> このガイドは [Composition API の導入](composition-api-introduction.html)[リアクティブの基礎](reactivity-fundamentals.html) を既に読んでいることを想定しています。Composition API に初めて触れる方は、まずそちらを読んでみてください。
66
77
## 引数
88

@@ -15,7 +15,7 @@
1515

1616
### プロパティ
1717

18-
`setup` 関数の第 1 引数は `props` 引数です。 標準コンポーネントで期待するように、`setup` 関数内の `props` はリアクティブで、新しい props が渡されたら更新されます。
18+
`setup` 関数の第 1 引数は `props` 引数です。標準コンポーネントで期待するように、`setup` 関数内の `props` はリアクティブで、新しい props が渡されたら更新されます。
1919

2020
```js
2121
// MyBook.vue
@@ -64,21 +64,24 @@ setup(props) {
6464

6565
### コンテキスト
6666

67-
`setup` 関数に渡される第 2 引数は `context` です。`context` は 3 つのコンポーネントプロパティを公開する一般的な JavaScript オブジェクトです。:
67+
`setup` 関数に渡される第 2 引数は `context` です。`context` は一般的な JavaScript オブジェクトで、`setup` の中で便利と思われる他の値を公開します:
6868

6969
```js
7070
// MyBook.vue
7171

7272
export default {
7373
setup(props, context) {
74-
// Attributes (Non-reactive object)
74+
// Attributes (Non-reactive object, equivalent to $attrs)
7575
console.log(context.attrs)
7676

77-
// Slots (Non-reactive object)
77+
// Slots (Non-reactive object, equivalent to $slots)
7878
console.log(context.slots)
7979

80-
// Emit Events (Method)
80+
// Emit events (Function, equivalent to $emit)
8181
console.log(context.emit)
82+
83+
// Expose public properties (Function)
84+
console.log(context.expose)
8285
}
8386
}
8487
```
@@ -88,13 +91,15 @@ export default {
8891
```js
8992
// MyBook.vue
9093
export default {
91-
setup(props, { attrs, slots, emit }) {
94+
setup(props, { attrs, slots, emit, expose }) {
9295
...
9396
}
9497
}
9598
```
9699

97-
`attrs``slots` はステートフルなオブジェクトです。コンポーネント自身が更新されたとき、常に更新されます。 つまり、分割代入の使用を避け、`attrs.x``slots.x` のようにプロパティを常に参照する必要があります。 また、`props` とは異なり、 `attrs``slots` はリアクティブ**ではない**ということに注意してください。 もし、`attrs``slots` の変更による副作用を適用したいのなら、`onUpdated` ライフサイクルフックの中で行うべきです。
100+
`attrs``slots` はステートフルなオブジェクトです。コンポーネント自身が更新されたとき、常に更新されます。つまり、分割代入の使用を避け、`attrs.x``slots.x` のようにプロパティを常に参照する必要があります。また、`props` とは異なり、`attrs``slots` のプロパティは **リアクティブではない** ということに注意してください。もし、`attrs``slots` の変更による副作用を適用したいのなら、`onBeforeUpdate` ライフサイクルフックの中で行うべきです。
101+
102+
`expose` の役割については後で説明します。
98103

99104
## コンポーネントプロパティへのアクセス
100105

@@ -105,7 +110,7 @@ export default {
105110
- `slots`
106111
- `emit`
107112

108-
言い換えると、以下のコンポーネントオプションには**アクセスできません**:
113+
言い換えると、以下のコンポーネントオプションには **アクセスできません**:
109114

110115
- `data`
111116
- `computed`
@@ -157,12 +162,35 @@ export default {
157162
setup() {
158163
const readersNumber = ref(0)
159164
const book = reactive({ title: 'Vue 3 Guide' })
160-
// ここでは明示的に ref の値を公開する必要があることに注意してください
165+
// ここでは明示的に ref の値を使用する必要があることに注意してください
161166
return () => h('div', [readersNumber.value, book.title])
162167
}
163168
}
164169
```
165170

171+
レンダリング関数を返すことで、他のものを返すことができなくなります。内部的には問題ありませんが、このコンポーネントのメソッドをテンプレート参照から親コンポーネントに公開したい場合には、問題となります。
172+
173+
この問題を解決するには、`expose` を呼び出して、外部コンポーネントのインスタンスで利用可能なプロパティを定義したオブジェクトを渡します:
174+
175+
```js
176+
import { h, ref } from 'vue'
177+
178+
export default {
179+
setup(props, { expose }) {
180+
const count = ref(0)
181+
const increment = () => ++count.value
182+
183+
expose({
184+
increment
185+
})
186+
187+
return () => h('div', count.value)
188+
}
189+
}
190+
```
191+
192+
この `increment` メソッドは、親コンポーネントでテンプレート参照を介して利用可能になります。
193+
166194
## `this` の使用
167195

168196
**`setup()` 内では、`this` は現在のアクティブなインスタンスへの参照にはなりません。** `setup()` は他のコンポーネントオプションが解決される前に呼び出されるので、`setup()` 内の `this` は他のオプション内の `this` とは全く異なる振る舞いをします。 これは、`setup()` を他のオプション API と一緒に使った場合に混乱を引き起こす可能性があります。

src/style-guide/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,6 +1284,7 @@ HTML では、空白を含まない属性値は引用符でくくらなくても
12841284
- `inheritAttrs`
12851285
- `props`
12861286
- `emits`
1287+
- `expose`
12871288

12881289
6. **コンポジション API** (コンポジション API を使用するためのエントリポイント)
12891290
- `setup`

0 commit comments

Comments
 (0)