- Component Guide for Vue "1.5"
- Do's and Don'ts
- Don't use
.synconv-bindoption - Don't use
twoWayprop option - Don't mutate props in vm
- Don't mutate props via
v-modelin template - Don't mutate props via expression in template
- Don't mutate elements of array prop or the array itself
- Don't mutate properties of an object prop
- Don't mutate store data directly
- Don't use
this.$dispatch - Don't use
this.$broadcast - Don't use
eventsoption - Use filters only in mustache interpolation and
v-bindexpressions - Don't use interpolation within attributes
- Use
v-htmlinstead of HTML interpolation
- Don't use
- Tools
- Do's and Don'ts
- Apply one way data flow. See Don't mutate props in vm.
- Apply one way data flow. See Don't mutate props in vm.
// NOK
props: {
externalProp: String
},
methods: {
someMethod () {
// don't mutate props!
this.externalProp = 'newValue'
}
}// OK
// $emit
methods: {
someMethod () {
this.$emit('update:external-prop', 'newValue')
}
}// OK
// $emit through update method
methods: {
someMethod () {
this.updateExternalProp('newValue')
},
updateExternalProp (value) {
this.$emit('update:external-prop', value)
}
}// OK
// mapOneWayProp creator
computed: {
// will emit 'update:external-prop' event by default with the new value
externalPropInt: mapOneWayProp('externalProp')
},
methods: {
someMethod () {
// you can assign safely
this.externalPropInt = 'newValue'
},
}// OK
// mapOneWayProps creator
computed: {
...mapOneWayProps({
'externalProp1Int': 'externalProp1', // will emit 'update:external-prop1' event by default with the new value
'externalProp2Int': 'externalProp2', // will emit 'update:external-prop2' event by default with the new value
})
},
methods: {
someMethod () {
// you can assign safely
this.externalProp1Int = 'newValue1'
this.externalProp2Int = 'newValue2'
},
}// OK
// get/set computed
computed: {
externalPropInt: {
get () {
return this.externalProp
},
set (value) {
this.$emit('update:external-prop', value)
// or
// this.updateExternalProp(value)
}
}
},
methods: {
someMethod () {
// you can assign safely
this.externalPropInt = 'newValue'
},
// updateExternalProp (value) { ... }
}// OK
// local data (initialized once, parent notified)
data () {
return {
someProp: this.externalProp // set initial value
}
},
methods: {
someMethod () {
// you can assign safely
this.someProp = 'newValue'
// if you want to update the externalProp too
this.$emit('update:external-prop', value)
// or
// this.updateExternalProp(value)
},
// updateExternalProp (value) { ... }
}// NOK
// component/index.js
props: {
externalProp: String
}
// component/template.html
// dont use v-model directly with props
<input type="text" v-model="externalProp">// OK
// v-one-way-model
// component/index.js
props: {
externalProp: String
}
// component/template.html
<input type="text" v-one-way-model="externalProp"> <!-- will emit `update:external-prop` event by default -->// OK
// one way computed + v-model
// component/index.js
props: {
externalProp: String
},
computed: {
externalPropInt: mapOneWayProp('externalPropInt')
}
// component/template.html
<input type="text" v-model="externalPropInt">- You may use additional techniques from Don't mutate props in vm
// NOK
// component/index.js
props: {
externalProp: String
}
// component/template.html
// don't assign values directly to props
<button @click="externalProp='newValue'">// OK
// handler method
// component/index.js
props: {
externalProp: String
},
methods: {
handleClick () {
this.$emit('update:external-prop', 'newValue')
}
}
// component/template.html
<button @click="handleClick">- You may use other techniques from Don't mutate props in vm
// NOK
// foo/index.js
props: {
externalArrayProp1: Array
},
methods: {
someMethods () {
// don't mutate array prop elements
this.externalArrayProp1[0] = 'newValue1'
// don't mutate array prop object element properties
this.externalArrayProp1[0].prop1 = 'newValue2'
// don't call mutable operations on array prop
this.externalArrayProp1.push(...)
this.externalArrayProp1.sort(...)
this.externalArrayProp1.splice(...)
// ...
}
},
// foo/template.html
// don't mutate array prop elements
<input type="text" v-model="externalArrayProp1[0]"></input>
// don't mutate array prop object element properties
<input type="text" v-model="externalArrayProp1[0].prop1"></input>
// don't call mutable operations on array prop
<button @click="externalArrayProp1.sort()"><button>- To avoid these use techniques from Don't mutate props in vm
// NOK
// foo/index.html
props: {
externalObjectProp1: Object
},
methods: {
someMethods () {
// don't mutate properties of an object prop
this.externalObjectProp1.prop1 = 'newValue1'
// don't add new properties to an object prop
this.externalObjectProp1.newProp1 = 'newValue2'
// don't remove properties from an object prop
delete this.externalObjectProp1.prop2
}
}
// foo/template.html
// don't mutate properties of an object prop
<input type="text" v-model="externalObjectProp1.prop1"></input>- To avoid these use techniques from Don't mutate props in vm
// NOK
vuex: {
getters: {
vuexProp1: state => state.some.prop1
}
},
methods: {
someMethod () {
// don't mutate store data directly
this.vuexProp1 = 'newValue1'
// nor do this
this.$store.state.some.prop2 = 'newValue2';
}
}
// also don't mutate them with `v-model` or expressions in template-
Use Vuex actions or mutations depending on your scenario. Here
someMethodcould be transformed into an action or mutation for example -
Mutating via
storeLinkeris a special exception (for now) but still, try to use Vuex instead if possible (mainly in new components) -
You may use and adapt techniques from Don't mutate props in vm
- Use
$emit(s) if you want to reach some of the parent components. You may need to re-emit the same or another event per parent. - Use
emit/emitOnNextTickif you want to reach a component/thing outside of the actual component hierarchy - Use Vuex action (action/mutation)
- Use
emit/emitOnNextTick - Use Vuex action (action/mutation)
- Use
v-on(@) in the template if the event emitted with$emit. (You may use$onin vm in some cases but@is preferred) - Use
eventBusMixinif the event emitted withemit/emitOnNextTick. (You may useonas well but you have to clean up after yourself which is done byeventBusMixinautomatically so that is the preferred way) - Use Vuex getters to react changes made by Vuex action if that is the case
<!-- in mustaches -->
{{ message | capitalize }}
<!-- in v-bind -->
<div :id="rawId | formatId"></div><!-- NOK -->
<button class="btn btn-{{ size }}"></button>
<!-- OK -->
<button :class="'btn btn-' + size"></button>
<!-- OK -->
<button :class="buttonClasses"></button>
computed: {
buttonClasses () {
return 'btn btn-' + size
}
}- so replace
{{{ somePropWithHtml }}}withv-html
- Useful to notify parent component about something (update of props, other events, etc.)
Doc: API/vm.$emit
- Useful for emitting global events
- Useful to notify components outside of the current component hierarchy (parents should be notified via
$emit) - To listen on events in components prefer using
eventBusMixininstead ofon, because it cleans up automatically on component destroy - Note: the events are emitted outside of the component vue life cycle which means that some component prop may not changed when the listener runs, in this cases
emitOnNextTickmay help
Doc: app/scripts/util/event-bus
Doc: app/scripts/mixins/event-bus
computed: {
someProp: {
get () {
// return local data
// return other computed
// return vuex prop
// ...
},
set (value) {
// set local data
// $emit event
// call vuex action
// emit global event
// ...
}
}
}Pros
- universal power tool
- plays well with
v-modeland/or prop mutation in vm
Cons
- you need to create a new prop with a new name (
isLoading=>isLoadingInt) - could be boilerplate => use the more compact
mapOneWayProp/mapOneWayPropsif applicable
Doc: app/scripts/utils/component/map-one-way-prop
Doc: app/scripts/utils/component/map-one-way-props
Pros
- plays well with
v-modeland/or prop mutation in vm - compact
Cons
- you need to create a new prop with a new name (
isLoading=>isLoadingInt) - could be to simple, if you need more power => get/set computed
- Watch out because it is a two way directive so it modifies the bound prop (which is ok for local data but NOK for props)
- It can be used with one way data flow if the prop is a get/set computed
- It can be used freely with local data
Doc: API/v-model
Note: use get/set computed or mapOneWayProp/mapOneWayProps instead until this gets implemented properly in Vue 2 (vue2 fork)
Doc: app/scripts/directives/one-way-model
Pros
- works the same way as
v-modelexcept it is a one way directive so it emits an event and/or calls a callback method on change - you don't need to create a new prop and think of a new name for it
Cons
- it only works well with templates, if you want to mutate a prop from the vm or from the vm too you may use get/set computed or
mapOneWayProp/mapOneWayProps