咱們在作項目的時候,應該會有這種狀況:javascript
"我寫了一個組件,而後作成了 npm 包,而後給好幾個項目一塊兒用。"vue
Vue 組件
也是能夠這麼幹的,因此在公司內部可能會將組件封裝成 npm 模塊
後分發給各個項目。java
不過在 Vue 的項目中,有兩個小地方可能須要精心處理下 (●’◡’●)git
EventBus
並非什麼獨立的東西,而是 Vue 的事件系統
的一個最佳實踐,算是一種使用方式:github
/** * EventBus. * src/event-bus.js */ export default new Vue({}) /** * 個人公用組件 my-component. */ import EventBus from 'src/event-bus' export default { ... methods: { // 觸發叫作 "SomeModule:SomeEvent" 的事件並傳了值 "Yeah~" 過去~ triggerSomeEvent () { EventBus.$emit('SomeModule:SomeEvent', 'Yeah~') }, // 爲個人組件註冊兩個事件~ registerEvents () { EventBus.$on('MyComponent:Event-01', value => { console.log('Event-01 in MyComponent: ', value) }), EventBus.$on('MyComponent:Event-02', value => { console.log('Event-02 in MyComponent: ', value) }) } }, created () { this.registerEvents() } }
當咱們的公用模塊在使用 EventBus 的時候,會有一個微小的問題,看這句話:vuex
import EventBus from 'src/event-bus'
我怎麼保證在使用我當前模塊的不一樣的項目中的 EventBus 的路徑都是 src/event-bus
呢?npm
因此,咱們須要抽象一層,讓模塊並不關心
這個 EventBus 是從哪裏引入的:this
// 咱們將 EventBus 作成插件,這樣就能夠在項目的任何組件內使用了. // 起名叫 $events. // 當檢測到 $events 存在的時候就使用,不存在的時候使用其餘方法. /** * 咱們將 event-bus 封裝爲一個插件. * plugin/event-bus.js */ export default { install (Vue) { const EventBus = new Vue({}) Vue.prototype.$events = EventBus Vue.EventBus = EventBus } } /** * 因此個人公用組件 my-component 要變爲: */ export default { ... methods: { // 觸發叫作 "SomeModule:SomeEvent" 的事件並傳了值 "Yeah~" 過去~ triggerSomeEvent () { if (this.$events) { this.$events.$emit('SomeModule:SomeEvent', 'Yeah~') } else { // 其餘方式... } }, // 爲個人組件註冊兩個事件~ registerEvents () { if (this.$events) { this.$events.$on('MyComponent:Event-01', value => { console.log('Event-01 in MyComponent: ', value) }), this.$events.$on('MyComponent:Event-02', value => { console.log('Event-02 in MyComponent: ', value) }) } else { // 其餘方式... } } }, created () { this.registerEvents() } } /** * 項目入口. * src/index.js */ import Vue from 'vue' import EventBus from 'plugin/event-bus' import MyComponent from 'my-component' Vue.use(EventBus) const Root = new Vue({ components: { MyComponent }, methods: { doSomething () { this.$events.$emit('MyComponent:Event-01', 'FA♂') } } })
OK,這樣咱們的組件就能夠在不一樣項目中適應 EventBus 了!prototype
這裏有一個組件 cklmercer/vue-events 就是解決這種問題而存在的.插件
這個問題僅僅存在於 Vue 1.0
的項目中,Vue 2.0 + Vuex 2.0
已經解決這個問題:
/** * 個人公用組件 my-component. */ import store from 'src/vuex/store' import actions from 'src/vuex/actions' import getters from 'src/vuex/getters' export default { ... store, vuex: { actions, getters }, computed: { userName () { // "getUsername" 是 Vuex 中定義好的 getter. return this.getUsername } }, methods: { changeDataInVuexByUsingAction () { // "setUserExperience" 是 Vuex 中定義好的 action. this.setUserExperience(450) } } }
那麼仍是一樣的問題,
我怎麼保證在使用我當前模塊的不一樣的項目中的 Vuex 的路徑都是 src/vuex
呢?
因此方法同樣啦,抽象出來引用路徑,讓模塊並不關心
是如何引入 Vuex 的:
// 咱們將 Vuex 作成插件,這樣就能夠在項目的任何組件內使用了. // 起名叫 $vuexer. // 當檢測到 $vuexer 存在的時候就使用 Vuex,不存在的時候就將數據寫入組件本身內部的 state 中. /** * 咱們將 event-bus 封裝爲一個插件. * plugin/event-bus.js */ export default { install (Vue, { store, actions, getters }) { const vuexer = new Vue({ store, actions, getters }) Vue.prototype.$vuexer = vuexer Vue.vuexer = vuexer } } /** * 項目入口. * src/index.js */ import Vue from 'vue' import Vuexer from 'plugin/vuexer' import store from 'src/vuex/store' import actions from 'src/vuex/actions' import getters from 'src/vuex/getters' import MyComponent from 'my-component' Vue.use(Vuexer, { store, actions, getters }) const Root = new Vue({ components: { MyComponent }, computed: { userExperience () { // "getExperience" 是在 Vuex 中定義好的 getter. return this.$vuexer.getExperience } }, methods: { changeUsernameInVuex () { // "setUsername" 是在 Vuex 中定義好的 setter. this.$vuexer.setUsername('John Smith') } } }) /** * 個人公用組件 my-component. */ export default { data () { return { _userName: '神祕用戶', _userExperience: 65535 } }, computed: { userName () { // 若是有 Vuexer, 若是木有 Vuexer... return this.$vuexer ? this.$vuexer.getUsername : this._userName } }, methods: { // 若是有 vuexer, 若是木有 Vuexer... changeDataInVuexByUsingAction () { const userExperience = 450 if (this.$vuexer) { this.$vuexer.setUserExperience(userExperience) } else { this._userExperience = userExperience } } } }
妥!⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄
至於爲何 Vue 2.0 + Vuex 2.0
木有這個問題:
// 在 Vue 2.0 中使用 Vuex 要這麼寫: // 建立一個組件. const Components = { template: `<div>{{ count }}</div>`, computed: { count () { return this.$store.getters.doneTodosCount // 這是一個 getter. } } }
注意 computed
中的 return this.$store.getters.doneTodosCount
,看看其中的 this.$store
,
是否是和 this.$vuexer
有點像? (°∀°)ノ
這裏還有一個組件 lancercomet/vuexer 就是爲 Vue 1.0
解決這個問題的!
完結撒花~
By LancerComet at 01:22, 2017.01.21.