-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tricks in Vue #52
Comments
There are some tricks which can't be found easily in Vue.js homepage. So, for convenient, I summarized them here. VueAccess Global Variable in TemplateHave you ever done something like this in lots of components? <template>
<a @click="window.open('...')"></a>
</template>
<script>
export default {
name: 'App',
data() {
return {
window: window
}
}
}
</script> or <template>
<a @click="bus.$emit('some-event')"></a>
</template>
<script>
export default {
name: 'App',
data() {
return {
bus: bus
}
}
}
</script> Actually, you don't have to, you can register Vue.prototype.window = window
Vue.prototype.bus = bus in the main.js or the entry file. Then you can use Reactive or Not ReactiveAlways, if we want a data reactive, we have to do something like this: data: {
newTodoText: '',
visitCount: 0,
hideCompletedTodos: false,
todos: [],
error: null
} Set some initial value to adds all the properties found in its data object to Vue's reactivity system. Things we need to take care about is:
Scoped Style Won't Work on Dynamically Inserted ElementsI always use the <template>
<div id="app" ref="app"></div>
</template>
<script>
export default {
name: 'App',
mounted() {
this.$refs.app.innerHTML = `<h1 class="App__title">App__title</h1>`
}
}
</script>
<style scoped>
.App__title {
color: red;
}
</style>
So, how do we solve this? <style scoped>
/deep/ .App__title {
color: red;
}
</style> They can be used to override child component style. Here is the doc. Smarter WatchersHave you ever written code like this: {
// ...
created() {
this.fetchPostList()
},
watch: {
searchInputValue() {
this.fetchPostList()
}
}
// ...
} Actually, you can simplify it by {
// ...
watch: {
searchInputValue:{
handler: 'fetchPostList',
immediate: true
}
}
// ...
} As the doc said:
$attrs and $listenersI don't know if you have used <div id="app">
<base-input
:value="value"
placeholder="parentPlaceholder"
otherAttrs="otherAttrs"
@input="inputCb"
@click="clickCb"
></base-input>
</div>
<script>
let BaseInput = {
name: 'base-input',
template: `
<div>
<input type="text" :value="value" :placeholder="placeholder" :otherAttrs="otherAttrs" @input="$emit('input',$event)" @click="$emit('click',$event)" @focus="focusCb" />
</div>`,
props: {
value: {
type: String
}
},
computed: {
listeners() {
const listeners = {
...this.$listeners,
focus: this.focusCb
}
return listeners
}
},
methods: {
focusCb(event) {
console.log('child', event)
}
}
}
window.app = new Vue({
el: '#app',
components: {
BaseInput
},
data: {
value: '',
parentPlaceholder: 'parentPlaceholder'
},
methods: {
inputCb(event) {
console.log(event)
},
clickCb(event) {
console.log(event)
}
}
})
</script> It's obviously tedious to bind every attribute and listener by hand. Actually, this is where let BaseInput = {
name: 'base-input',
template: `<div><input type="text" :value="value" v-bind="$attrs" v-on="listeners" /></div>`,
props: {
value: {
type: String
}
},
computed: {
listeners() {
const listeners = {
...this.$listeners,
// move `focus` in to `listeners` instead of adding one more `focus` listener.
focus: this.focusCb
}
return listeners
}
},
methods: {
focusCb(event) {
console.log('child', event)
}
}
} Vue-Router$router and $routeHave you ever wonder about the relationship between this.$router.currentRoute === this.$route //true VuexCommit Data by One MutationWe can't directly mutate let store = new Vuex.Store({
modules: {
// ...
},
mutations: {
updateName(state, data) {
state.name = data
},
updateChildrenCount(state, data) {
state.children.count = data
}
// other similar mutations
}
}) We can write a public mutation to do this like: let store = new Vuex.Store({
modules: {
// ...
},
mutations: {
replaceProperty(state, { path, data }) {
if (typeof path !== 'string') {
return
}
path = path.split('.')
let targetObj = path.slice(0, -1).reduce((re, key) => re[key], state)
targetObj[path.pop()] = data
}
}
}) Then we can mutate commit(
'replaceProperty',
{
path: 'name',
data: name
},
{ root: true }
)
commit(
'replaceProperty',
{
path: 'children.count',
data: data
},
{ root: true }
)
commit(
'replaceProperty',
{
path: 'some.other.deep.path.in.state',
data: data
},
{ root: true }
) It would also work for modules! Reference |
vuejs/vue#2417
The text was updated successfully, but these errors were encountered: