-
Notifications
You must be signed in to change notification settings - Fork 39
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
Vuex那些事儿 #106
Comments
mapState与mapGetter的区别是什么?我们都知道,这是我们从vuex查询数据的两种方式,那这两者到底有什么区别呢? // https://vuex.vuejs.org/api/#mapstate
mapState(namespace?: string, map: Array<string> | Object<string | function>): Object // https://vuex.vuejs.org/api/#mapgetters
mapGetters(namespace?: string, map: Array<string> | Object<string>): Object 如果看定义看不懂的话,可以移步TypeScript入门,或者到TypeScript官网自己学习,了解TypeScript中的Optional Property和strictNullChecks。
mapState: mapState(['bar','baz']) // 相当于state.bar
mapState({
foo: 'foo',
bar: state => state.bar,
baz(state) {
return state.baz + 'hhh'; // 用做计算
}
})
mapState('foo',['bar','baz']) // 这种形式不常用 mapGetters: mapGetters(['bar', 'baz']) // 直接映射
mapGetters({
barBuddy: 'bar', // 重命名映射
bazBuddy: 'baz',
}) 其实mapState和mapGetters的真正区别在于:
|
Vuex的plugins有什么用?暴露每个mutation的hooks,只接收一个store(初始化好的store)为参数。
最简单的开发和注入: const myPlugin = store => {
store.subscribe((mutation, state) => { })
} const store = new Vuex.Store({
plugins: [myPlugin]
}) 又见subscribe,这仍然是基于事件的"发布订阅者"编程模型,关于发布订阅者模型,可以参考webhook到底是个啥? Plugin内部提交mutationPlugins不能直接修改状态--这和我们的组件一样,可以通过commit mutation触发更改。 export default function createWebSocketPlugin (socket) {
return store => {
socket.on('data', data => {
store.commit('receiveData', data)
})
store.subscribe(mutation => {
if (mutation.type === 'UPDATE_DATA') {
socket.emit('update', mutation.payload)
}
})
}
} const plugin = createWebSocketPlugin(socket)
const store = new Vuex.Store({
state,
mutations,
plugins: [plugin]
}) 获取状态快照state的"snapshots"指的是,对mutation的状态做保留,例如当前的post-mutation state和pre-mutation state做对比。可以通过深拷贝实现: const myPluginWithSnapshot = store => {
let prevState = _.cloneDeep(store.state)
store.subscribe((mutation, state) => {
let nextState = _.cloneDeep(state)
// compare `prevState` and `nextState`...
// save state for next mutation
prevState = nextState
})
} snapshot适合在development阶段使用。当结合webpack或者Browserify,我们可以让构建工具处理: const store = new Vuex.Store({
plugins: process.env.NODE_ENV !=='production' ? [myPluginWithSnapshot] : []
}) 此处的环境变量的获取,需要用到webpack的DefinePlugin 这个webpack内置插件。关于DefinePlugin,可以参考Webpack Plugin那些事儿 Built-in Logger插件用于在控制台输出store的mutation信息,其实也是一种state snapshot。
相比vue-devtools,有以下优势:
/store/logger.js import createLogger from 'vuex/dist/logger';
const subscribedMutations = ['USER_INIT', 'DEVICE_EXPEND_STATUS'];
const logger = createLogger({
collapsed: false,
filter: (mutation) => subscribedMutations.includes(mutation.type),
transformer: (state) => state,
mutationTransformer: (mutation) => mutation,
logger: console,
});
export default logger; /store/index.js import logger from './logger';
export default new Vuex.Store({
plugins: [logger],
}) 注意:logger plugin仅仅用于development环境,因为它也本身属于state snapshot。 |
this.$store.commit()和mapMutation()哪种更好?当然是mapMutation,可以统一查看当前组件有多少mutation类型,但是需要注意命名不能和组件方法冲突。 import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment', // 不带payload映射,map `this.increment()` to `this.$store.commit('increment')`
'incrementBy' // 带payload映射,map `this.incrementBy(amount)` to `this.$store.commit('incrementBy', amount)`
]),
...mapMutations({
add: 'increment' // 重命名: map `this.add()` to `this.$store.commit('increment')`
})
}
} 直接使用this.$store.commit(): methods: {
foo() {
this.$store.commit('USER_INIT');
}
...
...
bar() {
this.$store.commit('USER_UPDATE');
}
} 当业务逐渐变复杂时,foo和bar之间会相隔很远,很难一目了然看清当前组件用到了哪些mutation。 methods: {
...mapMutations([
'USER_INIT',
'USER_UPDATE',
]),
foo() {
this['USER_INIT']();
}
...
bar() {
this['USER_UPDATE']();
}
} 很明显,这样很清晰。 |
mutation与action区别是什么?
mutation可以结构多个入参数吗?当然,加个判断就好了。 |
Modules的namespacing是什么操作?
modules: {
account: {
namespaced: true,
// module assets
state: { ... }, // module state is already nested and not affected by namespace option
getters: {
isAdmin () { ... } // -> getters['account/isAdmin']
},
actions: {
login () { ... } // -> dispatch('account/login')
},
mutations: {
login () { ... } // -> commit('account/login')
},
},
}
modules: {
foo: {
namespaced: true,
getters: {
// `getters` is localized to this module's getters
// you can use rootGetters via 4th argument of getters
someGetter (state, getters, rootState, rootGetters) {
getters.someOtherGetter // -> 'foo/someOtherGetter'
rootGetters.someOtherGetter // -> 'someOtherGetter'
},
someOtherGetter: state => { ... }
},
actions: {
// dispatch and commit are also localized for this module
// they will accept `root` option for the root dispatch/commit
someAction ({ dispatch, commit, getters, rootGetters }) {
getters.someGetter // -> 'foo/someGetter'
rootGetters.someGetter // -> 'someGetter'
dispatch('someOtherAction') // -> 'foo/someOtherAction'
dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'
commit('someMutation') // -> 'foo/someMutation'
commit('someMutation', null, { root: true }) // -> 'someMutation'
},
someOtherAction (ctx, payload) { ... }
}
}
}
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')
export default {
computed: {
// look up in `some/nested/module`
...mapState({
a: state => state.a,
b: state => state.b
})
},
methods: {
// look up in `some/nested/module`
...mapActions([
'foo',
'bar'
])
}
} 一个组件可能需要多个module的state,mutation和action,可以使用多个mapState么?亲测可以。 ...mapState({
user: 'user',
}),
...mapState({
Foo: 'device',
}), 上述内容完全可以满足需求,其他内容暂时不用涉猎。 |
一次vuex的状态变更经历哪些步骤?组件内的方法 Vuex是如何与Vue框架做双向数据绑定的?使用了Vue实例作为全局状态树_vm($$state) deep watch所有属性 |
用vuex也有一段时间了,但仅仅是很基础的用,没有学习高级特性,更没有深入过源码
由于手上负责的聊天项目较为复杂,深入学习vuex更显得很有必要,从而优化聊天部分的前端实现
基于以上目的,我将在这里记录自己在实践过程中的一些总结。
The text was updated successfully, but these errors were encountered: