Skip to content

Commit af299ae

Browse files
authored
Add programmatic events example (#1563)
1 parent 242508e commit af299ae

File tree

1 file changed

+63
-1
lines changed

1 file changed

+63
-1
lines changed

src/v2/guide/components-edge-cases.md

+63-1
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,69 @@ So far, you've seen uses of `$emit`, listened to with `v-on`, but Vue instances
173173
- Listen for an event only once with `$once(eventName, eventHandler)`
174174
- Stop listening for an event with `$off(eventName, eventHandler)`
175175

176-
You normally won't have to use these, but they're available for cases when you need to manually listen for events on a component instance. To learn more about their usage, check out the API for [Events Instance Methods](https://vuejs.org/v2/api/#Instance-Methods-Events).
176+
You normally won't have to use these, but they're available for cases when you need to manually listen for events on a component instance. They can also be useful as a code organization tool. For example, you may often see this pattern for integrating a 3rd-party library:
177+
178+
```js
179+
// Attach the datepicker to an input once
180+
// it's mounted to the DOM.
181+
mounted: function () {
182+
// Pikaday is a 3rd-party datepicker library
183+
this.picker = new Pikaday({
184+
field: this.$refs.input,
185+
format: 'YYYY-MM-DD'
186+
})
187+
},
188+
// Right before the component is destroyed,
189+
// also destroy the datepicker.
190+
beforeDestroy: function () {
191+
this.picker.destroy()
192+
}
193+
```
194+
195+
This has two potential issues:
196+
197+
- It requires saving the `picker` to the component instance, when it's possible that only lifecycle hooks need access to it. This isn't terrible, but it could be considered clutter.
198+
- Our setup code is kept separate from our cleanup code, making it more difficult to programmatically clean up anything we set up.
199+
200+
You could resolve both issues with a programmatic listener:
201+
202+
```js
203+
mounted: function () {
204+
var picker = new Pikaday({
205+
field: this.$refs.input,
206+
format: 'YYYY-MM-DD'
207+
})
208+
209+
this.$once('hook:beforeDestroy', function () {
210+
picker.destroy()
211+
})
212+
}
213+
```
214+
215+
Using this strategy, we could even use Pikaday with several input elements, with each new instance automatically cleaning up after itself:
216+
217+
```js
218+
mounted: function () {
219+
this.attachDatepicker('startDateInput')
220+
this.attachDatepicker('endDateInput')
221+
},
222+
methods: {
223+
attachDatepicker: function (refName) {
224+
var picker = new Pikaday({
225+
field: this.$refs[refName],
226+
format: 'YYYY-MM-DD'
227+
})
228+
229+
this.$once('hook:beforeDestroy', function () {
230+
picker.destroy()
231+
})
232+
}
233+
}
234+
```
235+
236+
See [this fiddle](https://jsfiddle.net/chrisvfritz/1Leb7up8/) for the full code. Note, however, that if you find yourself having to do a lot of setup and cleanup within a single component, the best solution will usually be to create more modular components. In this case, we'd recommend creating a reusable `<input-datepicker>` component.
237+
238+
To learn more about programmatic listeners, check out the API for [Events Instance Methods](https://vuejs.org/v2/api/#Instance-Methods-Events).
177239

178240
<p class="tip">Note that Vue's event system is different from the browser's <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget">EventTarget API</a>. Though they work similarly, <code>$emit</code>, <code>$on</code>, and <code>$off</code> are <strong>not</strong> aliases for <code>dispatchEvent</code>, <code>addEventListener</code>, and <code>removeEventListener</code>.</p>
179241

0 commit comments

Comments
 (0)