
安装 vuex (在创建项目的时候我们已经安装了),如果没有那就 npm 一下呗!

我们在写文章的时候 -> 记住不要用那么多术语
话又说回来,我们该如何理解 vuex 是什么呢?
用之前我们弄得 store 来理解它 -> 用来管理数据的工具! -> 简单来说,它就是个对象,提供了一些 API,让我们可以读数据(查)和写数据(增删改)!
总之,所谓「管理」就是「读写」,所谓「状态」就是「数据」! -> 「状态管理模式」即是「数据读写工具」(关于「模式」的解释,芳芳也不知道是什么意思……)

很难 -> 因为对于中国人而言,它是英文教学的 -> 所以我们只好用 CRM 大法看官方文档学习它了!
很多时候我们学不会某个东西,并不是因为我们的智商问题,而是入门教程实在太辣鸡了!
代码:Demo
💡:store可不是那个参数{}?

我们传的state显然是复制到了store这个实例上! -> 跟我们之前...tagStore一样……
💡:你以为在state里边不能写方法吗?

💡:读写状态的操作?
store.state.countmutations(改动之意)里边做!
data即是state,methods即是mutations-> Vue 很贱,总是发明一些新的单词来增加我们的记忆负担! -> 其实是延用了某些设计才搞得这些新单词!
进一步分析一下「写」:

this可能是window
不要用this哈,如果你用了,那也是白用了! -> 传个state形参,然后state.count += 1这样改!
如何调用increment方法?
显然不会用这种智障姿势:
store.mutations.increment(store.state)
vuex 给我们封装了一个 API:
// 不需要我们自己传 state 参数!
store.commit('increment')
讽刺:Vuex 给了我们非常多的新单词,但这些单词只是换汤不换药! -> 本来数据叫
data的,现在则是叫state,本来改变数据直接调用increment就好了,但现在不能直接调,而是透过commit提交一下'increment'方法名来调!
💡:vuex 真得比我们之前封装的store好用吗?

没有好用到哪儿去! -> vuex 改变了我们操作数据的姿势!
💡:如何给mutation传参?(如何给改动数据的 API 传参?)

有的时候,如果你代码写得不好,那么你就去发明概念,你概念发明好了,然后写一些非常简单的库,也可以让这些「简单的」库看起来变得非常牛逼!
我很菜,但我可以捣鼓一些你不懂的概念,让我看起来很牛逼,很高级!
💡:单一状态树是什么?
简单来说就是对象(包含了全部的应用层级状态)
{
state: {
count: 0,
user: {
name: 'frank',
age: 18
}
}
}
所谓的树 -> 数据的嵌套层级很深,看起来像是一棵树!
应用层级状态 -> 应用就是「你的这个项目」、层级就是「一层层的组件」,毕竟一个项目是由很多个组件组合而成的、状态即「数据」 -> 合起来就是「你的项目里边所有组件的数据」 -> 不说人话的解释就是「应用层级状态」
唯一数据源 -> 我们整个应用没有第二个数据,那就叫做唯一数据源!
为了权威性,所以增加了很多术语,但其实没啥用呀! -> 真正学习编程,一定要了解这个东西的本质才行! ->
store本质就是一个对象!
💡:单一状态树让我们能够直接地定位任一特定的状态片段?
我们可以获取全局对象里边的任意一个数据片段,如count等
💡:单状态树和模块化并不冲突?

就是分文件呗!
💡:如何在组件中获取状态?
需要计算属性 -> 计算属性写在@Component这个装饰器里边!

如果你只想用一次,那就用data姿势呗!但大部分情况都不止用一次哈!
总之,count会计算依赖 -> store.state.count变了,那么count就会变!
💡:template里边可以拿到import的store吗?

如何解决?
很简单,你改成是一个函数名不就行了:

另一种解决姿势:

Vue.use(Vuex)这行代码,use操作会去调用Vuex里边的一些东西,这些东西会在Vue的原型上绑定一些共用属性!
Vue.use(Vuex)就是在安装这个Vuex插件,也就是为Vue.prototype挂载一个$store属性! -> 也就是把 store 给绑定了: Vue.prototype.$store = store
当我们:
new Vue({
router,
store,
render: (h) => h(App),
}).$mount("#app");
这样做时,就是传一个store给$store了!
话说,为啥不在index.ts里边一开始就传了?而是跑去main.ts里边传? -> 就是这样设计的!因为符合初始化语法哈! -> 相当于是注册了,要初始化才能使用!
所以另一种姿势就这样这样:

💡:计算属性与data同名,你猜template里边会渲染谁?

'[Vue warn]: The computed property "recordList" is already defined in data.'
computed来获取 -> computed:{ count() { return this.$store.state.count } }this.$store.commit或者是this.store.commit使用$store不需要我们import store
对比我们之前写的自定义store,vuex 并没有好在哪里,而且很不简洁!(很复杂) -> 也比不上那种window姿势! -> 明明使用 vuex 没有好处,为啥还要学呢? -> 因为大家都在学呗! -> 前端的整体水平有待提高,毕竟什么是好处,什么是坏处,一点深刻认识都没有!
批判一个东西前先学会它,不然,别人是不信你所说的!
action是用来调用method的 -> 异步操作! -> 旺财升级版会用到它!
import index2 的代码!(我没有这样做,我是一个组件一个组件这样慢慢改……)fetchRecords -> createRecord -> saveRecords
代码:Demo
💡:注释是给初学者看的,作为同行不需要看,所以把代码里边存在的注释都给删咯!
💡:改用 vuex,那么就有意去削掉methods里边的this了

可以用this,但就是让你不要用!
💡:改代码时,步子不要迈得太大
如,方方一开始就把所有的import index2都给删了! -> 这样每次测试是否把代码修改成功都会报错!
💡:关于注释:// TODO?

todo意味着你之后要去修改代码的,而且如果遗漏了 todo 没有完成,那么在你提交代码时,会告诉你这个:

你可以 review 一下看看有哪些 todo,也可以不管未完成的todo,直接 commit。
💡:mutations里边的方法都有返回值吗?
是没有的,直接改state里边的数据就行了!

往
mutations里边添加方法 -> 每个方法总是需要传state这个形参!
代码:Demo
如果一开始就用 Vuex ,那就不用改代码了,但是这样一来,就不能更好地理解 Vuex 了!
💡:一定要重复fetch?
Tags.vue需要fetch,Labels.vue也需要fetch -> 因为如果只有Tags.vue有fetch,那么你直接刷新Labels.vue是拿不到TagList的,因为Tags.vue还没有渲染呢,以致于全局state还咩有拿到值……
每次切换路由所对应的组件都会重新fetch -> 牺牲点性能,保证每次拿到的都是最新的数据!
每次切换路由 -> 意味着切换组件 -> 意味着每次都会执行
created钩子!
💡:出现两次一模一样的代码?

代码重复出现两次,可优化亦可不优化! -> 如果优化,那就用 mixin 呗!
mixin很好用,它可以把多个组件都用到的方法收拢到一个组件里边 -> 需要mixin的组件extends一下mixins就好了!
/src/mixins/createTags.js -> 为啥加s,因为src目录下大多有多个加s的目录,简单来说,我们可能不止会用到一个mixinmixins是个对象,直接导出就好了 -> 为啥不是.ts文件? -> 因为有this会报错!而用.js则不会报错!代码:Demo
💡:名字修改?
在组件里边使用mixin时,我们导入的是这个mixin的文件名

我们改成是tagHelper.js了,如果是类,那就是大写TagHelper,而对象则是小写!
💡:如何禁用 Eslint 对某一行代码报错?
自己谷歌搜! -> 在 ts 里边使用 js,Eslint 可能无法通过!
💡:在写代码的过程中,发现往 ts 里边 混入 js 代码,是危险的操作?
一个js文件,会污染整个用 ts 写的项目!

但如果改成 ts,又得报错了:

我们用的类组件,是使用第三方工具的,而这个第三方工具也是依赖官方所提供的Vue Class Component的,在 官网 里边我们找到「如何配合ts使用mixin」
过程挺麻烦的 -> 你选择了使用 ts,那就相当于选择了一条高端之路!
做法 -> 把mixin声明成类组件 -> 这意味我们的文件名要改成大写的TagHelper了!

这个名字问题 -> 如果
xxx组件也有同一个叫create的方法,那么就会被覆盖了!
题外话:


代码:Demo
💡:commit的返回值是void?

如何拿到我们要的返回值?

给 tag 初始值的原因:

因为我们原本就是这样做的!

如何解决?
vue-property-decorator 的文档 -> 发现咩有答案Vue Class Component 的文档 -> 找到了答案 -> 用原生自带的get和set函数来写计算属性(写在 class 里边),而不是把computed作为一个选项传给@Component这个注解!
用了 TS,那么你就得严谨看待 -> 不要看到报错,就改成是 JS 的 -> 你要把网上能搜索的资料(不管是英文还是中文)都给测试一遍 -> 排除法,解决 bug!
对了,除了这个EditLabel.vue需要用到computed,其它的组件也用到了,如果你不想你的代码成为屎山,那么你就把之前写的computed,改成是get姿势的! -> 千万不要认为这样很费时间!
改法(全局搜索用到computed的.vue文件):

代码:Demo
关于set,我们没有用到 -> 所以就不用管了!
💡:是否用了get之后,所拿到的值也会有缓存的效果?
是的,因为计算属性本质上就是一个由getter/setter作为键值的对象

💡:莫名其妙的报错?

我们是如何找到错误原因的?
先把函数体里边的代码给注释了 -> 传一个state参数试试报不报错? -> 不报错 -> 传第一个参数试试报不报错? -> 不报错 -> 传第三个参数试试报不报错? -> 报错了!
所以可以看到,写在mutations里边的方法只能接受一个参数 -> 所以我们把参数改成是对象形式的即可解决之!
updateTag(state, object: { id: string, name: string }) {}
注意,一般我们管接收参数的形参叫playload!
💡:一个 bug,对用户 input的值同时用了 watcher 和 @input!
会触发两次操作! -> 我们只需要触发一次! -> 如果有单元测试会好很多!
💡:VS Code 在重构变量名时是通过字符串匹配改的,而 webstorm 则是透过语义来改的!
如你打log的参数字符串里边有你要改的字符,那么 VS Code 也会把它给改了!
💡:Vuex 的弊端?
在commit的时候,如果传的字符串方法名参数写错了,那么它是不会报错的!
💡:用户重新刷新页面的问题?

以后的数据读和写,都透过$store来搞! -> 有点麻烦 -> 但还是有小技巧,让我们不用这样做的! -> 总之,先把思路给走通咯!
接下来总结一下使用 Vuex 的常用套路!
💡:安装Vuex?
Vue.use(Vuex) -> 安装new Vue({store}) -> 初始化 -> 让我们可以this.$store💡:定义store?

💡:如何组件里边使用store?
分为读和写:

💡:更厉害的旺财项目?
会用到 actions 这个选项! -> 不用听方方讲,直接用 CRM 大法看文档学习就好了,毕竟经历过方方的系统课程之后,就没有什么新知识了
全局状态管理 -> Vue 就 Vuex 这么一个方案 -> 我们只用了本地数据管理,没有用异步操作获取远程数据,所以也就没有用actions了!
接下来完成「统计页面」!
问题缘由:

什么是存粹的对象?
我们 var obj = {} 相当于是执行了这个语句:
var obj = Object.create(Object.prototype)
这个 obj 是不存粹的,因为它生来自带了Object的一系列内置属性和方法
如何才能造个存粹的对象?
很简单,直接这样:
var obj = Object.create(null)

为什么需要纯粹的对象?
「纯粹」的对象适合用于存储键值对数据,而且没有隐式的类型转换,更加直观
总之,除了继承了Object.prototype这点,Object.create(null) 和 {}之间没有别的区别了,在操作对象这一点上完全一致,存取的性能没差啦。但如果并不 care 自己的空对象继承了Object的话,我建议大家还是使用{}来声明吧,因为在创建性能上{}比Object.create(null) 快了 20 倍呢!!!