Vue开发技巧

274 阅读2分钟

优雅更新props

更新 prop 在业务中是很常见的需求,但在子组件中不允许直接修改 prop,因为这种做法不符合单向数据流的原则,在开发模式下还会报出警告。因此大多数人会通过 $emit 触发自定义事件,在父组件中接收该事件的传值来更新 prop。

child.vue

export defalut {
    props: {
        title: String  
    },
    methods: {
        changeTitle(){
            this.$emit('change-title', 'hello')
        }
    }
}

parent.vue

<child :title="title" @change-title="changeTitle"></child>

export default {
    data(){
        return {
            title: 'title'
        }  
    },
    methods: {
        changeTitle(title){
            this.title = title
        }
    }
}

这种做法没有问题,我也常用这种手段来更新 prop。但如果你只是想单纯的更新 prop,没有其他的操作。那么 sync 修饰符能够让这一切都变得特别简单。

parent.vue

<child :title.sync="title"></child>
export defalut {
    props: {
        title: String  
    },
    methods: {
        changeTitle(){
            this.$emit('update:title', 'hello')
        }
    }
}

只需要在绑定属性上添加 .sync,在子组件内部就可以触发 update:属性名 来更新 prop。可以看到这种手段确实简洁且优雅,这让父组件的代码中减少一个“没必要的函数”。

provide/inject

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。 简单来说,一个组件将自己的属性通过 provide 暴露出去,其下面的子孙组件 inject 即可接收到暴露的属性。 APP.vue

export default {
    provide() {
        return {
            app: this
        }
    } 
}

child.vue

export default {
    inject: ['app'],
    created() {
        console.log(this.app) // App.vue实例
    }
}

在 2.5.0+ 版本可以通过设置默认值使其变成可选项:

export default {
    inject: {
        app: {
            default: () => ({})
        }
    },
    created() {
        console.log(this.app) 
    }
}

如果你想为 inject 的属性变更名称,可以使用 from 来表示其来源:

export default {
    inject: {
        myApp: {
            // from的值和provide的属性名保持一致
            from: 'app',
            default: () => ({})
        }
    },
    created() {
        console.log(this.myApp) 
    }
}

需要注意的是 provide 和 inject 主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。但是某些时候,或许它能帮助到我们。

小型状态管理器

大型项目中的数据状态会比较复杂,一般都会使用 vuex 来管理。但在一些小型项目或状态简单的项目中,为了管理几个状态而引入一个库,显得有些笨重。 在 2.6.0+ 版本中,新增的 Vue.observable 可以帮助我们解决这个尴尬的问题,它能让一个对象变成响应式数据:

// store.js
import Vue from 'vue'

export const state = Vue.observable({ 
  count: 0 
})

使用:

<div @click="setCount">{{ count }}</div>
import {state} from '../store.js'

export default {
    computed: {
        count() {
            return state.count
        }
    },
    methods: {

当然你也可以自定义 mutation 来复用更改状态的方法:

import Vue from 'vue'

export const state = Vue.observable({ 
  count: 0 
})

export const mutations = {
  SET_COUNT(payload) {
    if (payload > 0) {
        state.count = payload
    } 
  }
}

使用:

import {state, mutations} from '../store.js'

export default {
    computed: {
        count() {
            return state.count
        }
    },
    methods: {
        setCount() {
            mutations.SET_COUNT(100)
        }
    }
}

转载

10个Vue开发技巧助力成为更好的工程师