Skip to content

Commit d7fed38

Browse files
authored
Moving Components Page into its Own Category (#908)
* Moving Components Page into its Own Category * Add caveat * Correct link (#1548) * Update components.md (#1557) I removed the underscores around "prop"erty. I'm not sure what was intended there- maybe bold or italics, but I figured at minimum it should be removed until someone can correct it better. * (fix) add missing quote in custom-input example (#1570) * Translate into Japanese * fix: invalid link * chore: unify the terms
1 parent 1012e31 commit d7fed38

File tree

13 files changed

+2087
-1323
lines changed

13 files changed

+2087
-1323
lines changed

_config.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,3 @@ alias:
187187
examples/svg.html: v2/examples/svg.html
188188
examples/todomvc.html: v2/examples/todomvc.html
189189
examples/tree-view.html: v2/examples/tree-view.html
190-

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "jp.vuejs.org",
33
"private": true,
44
"hexo": {
5-
"version": "3.4.4"
5+
"version": "3.6.0"
66
},
77
"dependencies": {
88
"hexo": "^3.4.2",

src/v2/api/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1434,7 +1434,7 @@ updated: 2018-03-21
14341434

14351435
- **詳細:**
14361436

1437-
親スコープの (`.native` 修飾子なしの) `v-on` イベントリスナーを含みます。これは、`v-on="$listeners"` を介して内部コンポーネントに渡すことができます。高次コンポーネントを作成するときに便利です
1437+
親スコープの (`.native` 修飾子なしの) `v-on` イベントリスナーを含みます。これは、`v-on="$listeners"` を介して内部コンポーネントに渡すことができます。透過的なラッパーコンポーネントを作成するときに便利です
14381438

14391439
## インスタンスメソッド / データ
14401440

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
---
2+
title: Custom Events
3+
type: guide
4+
order: 103
5+
---
6+
7+
> ⚠️注意: この内容は原文のままです。現在翻訳中ですのでお待ち下さい。🙏
8+
9+
> This page assumes you've already read the [Components Basics](components.html). Read that first if you are new to components.
10+
11+
## Event Names
12+
13+
Unlike components and props, event names don't provide any automatic case transformation. Instead, the name of an emitted event must exactly match the name used to listen to that event. For example, if emitting a camelCased event name:
14+
15+
```js
16+
this.$emit('myEvent')
17+
```
18+
19+
Listening to the kebab-cased version will have no effect:
20+
21+
```html
22+
<my-component v-on:my-event="doSomething"></my-component>
23+
```
24+
25+
Unlike components and props, event names will never be used as variable or property names in JavaScript, so there's no reason to use camelCase or PascalCase. Additionally, `v-on` event listeners inside DOM templates will be automatically transformed to lowercase (due to HTML's case-insensitivity), so `v-on:myEvent` would become `v-on:myevent` -- making `myEvent` impossible to listen to.
26+
27+
For these reasons, we recommend you **always use kebab-case for event names**.
28+
29+
## Customizing Component `v-model`
30+
31+
> New in 2.2.0+
32+
33+
By default, `v-model` on a component uses `value` as the prop and `input` as the event, but some input types such as checkboxes and radio buttons may want to use the `value` attribute for a [different purpose](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/checkbox#Value). Using the `model` option can avoid a conflict in such cases:
34+
35+
```js
36+
Vue.component('base-checkbox', {
37+
model: {
38+
prop: 'checked',
39+
event: 'change'
40+
},
41+
props: {
42+
checked: Boolean
43+
},
44+
template: `
45+
<input
46+
type="checkbox"
47+
v-bind:checked="checked"
48+
v-on:change="$emit('change', $event.target.value)"
49+
>
50+
`
51+
})
52+
```
53+
54+
Now when using `v-model` on this component:
55+
56+
```js
57+
<base-checkbox v-model="lovingVue"></base-checkbox>
58+
```
59+
60+
the value of `lovingVue` will be passed to the `checked` prop. The `lovingVue` property will then be updated when `<base-checkbox>` emits a `change` event with a new value.
61+
62+
<p class="tip">Note that you still have to declare the <code>checked</code> prop in component's <code>props</code> option.</p>
63+
64+
## Binding Native Events to Components
65+
66+
There may be times when you want to listen directly to a native event on the root element of a component. In these cases, you can use the `.native` modifier for `v-on`:
67+
68+
```html
69+
<base-input v-on:focus.native="onFocus"></base-input>
70+
```
71+
72+
This can be useful sometimes, but it's not a good idea when you're trying to listen on a very specific element, like an `<input>`. For example, the `<base-input>` component above might refactor so that the root element is actually a `<label>` element:
73+
74+
```html
75+
<label>
76+
{{ label }}
77+
<input
78+
v-bind="$attrs"
79+
v-bind:value="value"
80+
v-on:input="$emit('input', $event.target.value)"
81+
>
82+
</label>
83+
```
84+
85+
In that case, the `.native` listener in the parent would silently break. There would be no errors, but the `onFocus` handler wouldn't be called when we expected it to.
86+
87+
To solve this problem, Vue provides a `$listeners` property containing an object of listeners being used on the component. For example:
88+
89+
```js
90+
{
91+
focus: function (event) { /* ... */ }
92+
input: function (value) { /* ... */ },
93+
}
94+
```
95+
96+
Using the `$listeners` property, you can forward all event listeners on the component to a specific child element with `v-on="$listeners"`. For elements like `<input>`, that you also want to work with `v-model`, it's often useful to create a new computed property for listeners, like `inputListeners` below:
97+
98+
```js
99+
Vue.component('base-input', {
100+
inheritAttrs: false,
101+
props: ['label', 'value'],
102+
computed: {
103+
inputListeners: function () {
104+
var vm = this
105+
// `Object.assign` merges objects together to form a new object
106+
return Object.assign({},
107+
// We add all the listeners from the parent
108+
this.$listeners,
109+
// Then we can add custom listeners or override the
110+
// behavior of some listeners.
111+
{
112+
// This ensures that the component works with v-model
113+
input: function (event) {
114+
vm.$emit('input', event.target.value)
115+
}
116+
}
117+
)
118+
}
119+
},
120+
template: `
121+
<label>
122+
{{ label }}
123+
<input
124+
v-bind="$attrs"
125+
v-bind:value="value"
126+
v-on="inputListeners"
127+
>
128+
</label>
129+
`
130+
})
131+
```
132+
133+
Now the `<base-input>` component is a **fully transparent wrapper**, meaning it can be used exactly like a normal `<input>` element: all the same attributes and listeners will work.
134+
135+
## `.sync` Modifier
136+
137+
> New in 2.3.0+
138+
139+
In some cases, we may need "two-way binding" for a prop. Unfortunately, true two-way binding can create maintenance issues, because child components can mutate the parent without the source of that mutation being obvious in both the parent and the child.
140+
141+
That's why instead, we recommend emitting events in the pattern of `update:my-prop-name`. For example, in a hypothetical component with a `title` prop, we could communicate the intent of assigning a new value with:
142+
143+
```js
144+
this.$emit('update:title', newTitle)
145+
```
146+
147+
Then the parent can listen to that event and update a local data property, if it wants to. For example:
148+
149+
```html
150+
<text-document
151+
v-bind:title="doc.title"
152+
v-on:update:title="doc.title = $event"
153+
></text-document>
154+
```
155+
156+
For convenience, we offer a shorthand for this pattern with the `.sync` modifier:
157+
158+
```html
159+
<text-document v-bind:title.sync="doc.title"></text-document>
160+
```
161+
162+
The `.sync` modifier can also be used with `v-bind` when using an object to set multiple props at once:
163+
164+
```html
165+
<text-document v-bind.sync="doc"></text-document>
166+
```
167+
168+
This passes each property in the `doc` object (e.g. `title`) as an individual prop, then adds `v-on` update listeners for each one.
169+
170+
<p class="tip">Using <code>v-bind.sync</code> with a literal object, such as in <code>v-bind.sync="{ title: doc.title }"</code>, will not work. If you want to include multiple, unrelated data properties in the same <code>v-bind.sync</code>, we recommend creating a computed property that returns an object.</p>

0 commit comments

Comments
 (0)