你厌倦了Vuex
的状态管理吗
-
你厌倦了诸如
State
、Getter
、Mutation
、Action
、Module
和各种map
映射方法…… 等等复杂的概念吗? -
你是否想以更优雅、更简易、更轻量、更具面向对象思想的管理你的数据和方法?
-
你是否想为你的项目提供一个
Service
模块,以便更好的管理页面无关逻辑?
那么以前的 Vue
状态管理库都不能满足你的需求!!!你应该考虑使用rx-srv
来助力你的开发体验!!!
你真的想要那么复杂的状态管理库吗?
现在放下所有的旧思想,认真的想一个问题:你真的想要那么复杂的状态管理库吗?
请看下面的代码
import RxService from 'rx-srv'
import {Service} from "typedi";
@Service()
class UserService extends RxService {
public userName: string = 'Tom'
public userAge: number = 18
public userAddress = {
province: '安徽',
city: '池州'
}
constructor() {
super();
super.observe()
window['UserService'] = this
}
public rename(name: string) { this.userName = name }
public growUp() { this.userAge ++ }
public updateProvince(province: string) { this.userAddress.province = province }
public updateCity(city: string) { this.userAddress.city = city }
}
export const userService = Container.get(UserService) // 获取单例的 UserService
如果我说上面的 userService
的属性(如:userName
)都是响应式的,可以用于存储跨页面的状态值,然后每个Service
可以写你需要的方法(如rename()
)去处理页面无关逻辑。
上面的这个类是不是能满足你所有的状态管理和功能逻辑的需求呢?
如何在前端页面中使用呢?
<template>
<div id="app">
User Info:
<div>Name: {{userService.userName}}</div>
<div>Age: {{userService.userAge}}</div>
<div>Addr: {{userService.userAddress.province}} - {{userService.userAddress.city}}</div>
<div>
<button @click="growUp">Grow Up</button>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "vue-property-decorator";
import { userService } from "@/service";
@Component
export default class App extends Vue {
public userService = userService
public growUp() {
this.userService.growUp()
}
}
</script>
<style scoped>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
height: 100%;
overflow: hidden;
width: 100%;
}
</style>
在前端页面中使用
我们不需要诸如 this.$store
这样隐式的方法,显得非常突兀(并且安装的时候需要隐式的挂载到每个Vue实例中)
我们也不需要诸如mapState
这样第一眼看过去非常懵逼的,需要学习成本的奇怪概念。
我们只用导入userService
,然后就可以使用它的属性及方法。
怎么做到使得UserService
的属性值是响应式的呢?
读到这里你是否会有疑问,你是怎么做到使得UserService
的属性值是响应式的?会不会有内存或者性能的问题?
首先,使得属性值是响应式的实现非常简单,如下rx-srv
源码
import Vue from "vue";
const sharedPropertyDefinition = {
enumerable: true,
configurable: true,
get: () => {},
set: (key: string) => {}
}
export function proxy(target: object, sourceKey: string, key: string) {
sharedPropertyDefinition.get = function proxyGetter() {
return this[sourceKey][key]
}
sharedPropertyDefinition.set = function proxySetter(val) {
this[sourceKey][key] = val
}
Object.defineProperty(target, key, sharedPropertyDefinition)
}
class RxService {
private __data: object = {}
constructor() { }
public observe() {
Reflect.ownKeys(this).forEach((key: string) => {
if (key.startsWith('_') || key.startsWith('$')) return
this['__data'][key] = this[key]
Reflect.deleteProperty(this, key)
proxy(this, `__data`, key)
})
Vue.observable(this['__data'])
}
}
export default RxService
源码地址见GitHub:github.com/simo-an/rx-…
在上面代码中observe()
方法中我们将Service
的属性先剪切到__data
属性上,再代理回Service
,最后利用Vue
提供的observable()
方法将属性值做成响应式的,即实现了我们需要的功能。
在Vuex
中我们至少创建了一个Vue
实例,但是在rx-srv
中我们甚至不需要这个Vue
实例的消耗,你说这是不是在性能和内存上都做到了极简?
快去使用一下吧
你可以现在你的Demo
试用一下吧 ( www.npmjs.com/package/rx-… )
yarn add rx-srv -D
yarn add reflect-metadata -D
yarn add typedi -D
其中安装 reflect-metadata
和 typedi
是为了让代码更加优雅的创建单例Service
。
你需要在main.ts
中首先导入reflect-metadata
,如下
import 'reflect-metadata'
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
好了,以上就是全部内容了,欢迎使用之后给出意见,帮助我们一起将这个库做的更好!同时也欢迎 start、fork。
全部代码见:github.com/simo-an/rx-…