当前位置: 首页 > news >正文

【VUE2】第五期——VueCli创建项目、Vuex多组件共享数据、json-server——模拟服务端api

黑马程序员视频地址:091-vuex的基本认知_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1HV4y1a7n4?vd_source=0a2d366696f87e241adc64419bf12cab&spm_id_from=333.788.videopod.episodes&p=91


目录

1 VueCli 自定义创建项目

2 Eslint代码规范

2.1 规则表 

2.2 手动修改对照文档

2.3 通过插件修改

3 Vuex

3.1 创建仓库

3.1.1 安装Vuex包

3.1.2 创建仓库

3.1.3 将仓库挂载到vue实例上

3.2 仓库中的共享数据与方法 

3.2.1 state状态(数据)

3.2.1.1 提供数据

3.2.1.2 访问数据

3.2.1.2.1 $store

 3.2.1.2.2 mapState

3.2.1.2 修改数据与严格模式

3.2.2 mutations(同步方法)

3.2.2.1 提供方法

3.2.2.2 使用方法

3.2.2.2.1 $store

3.2.2.2.2 mapMutations

3.2.3 actions(异步方法)

3.2.3.1 提供方法 

3.2.3.2 使用方法

3.2.3.2.1 $store

3.2.3.2.2 mapActions

3.2.4 getters(计算数据)

3.2.4.1 提供计算数据

3.2.4.2 使用计算数据

3.2.4.2.1 $store

 3.2.4.2.2 mapGetters

3.2.5 总结

3.3 module模块化

3.3.1 提供数据/方法

 3.3.2 访问数据/方法

3.3.2.1 打印对比是否开启命名空间对$store中属性的影响 

3.3.2.2 未开启命名空间

3.3.2.3 开启命名空间

 4 json-server——模拟服务端api

4.1 使用步骤 

4.2 使用语法

4.2.1 获取数据

4.2.2 修改数据


1 VueCli 自定义创建项目

1.安装脚手架 (已安装)

npm i @vue/cli -g

2.创建项目

vue create hm-exp-mobile

以上两步与之前普通创建vue2项目一样


不同操作:

Vue CLI v5.0.8
? Please pick a preset:
  Default ([Vue 3] babel, eslint)
  Default ([Vue 2] babel, eslint)
> Manually select features     选自定义


3.配置自定义项目 

  • 手动选择功能

  • 选择vue的版本

  3.x
> 2.x

  • 是否使用history模式

  • 选择css预处理

  • 选择eslint的风格 (eslint 代码规范的检验工具,检验代码是否符合规范)

  • 比如:const age = 18; => 报错!多加了分号!后面有工具,一保存,全部格式化成最规范的样子

  • 选择校验的时机 (直接回车)

  • 选择配置文件的生成方式 (直接回车)

  • 是否保存预设,下次直接使用? => 不保存,输入 N

  • 等待安装,项目初始化完成

  • 启动项目
npm run serve

2 Eslint代码规范

2.1 规则表 

ESLint:是一个代码检查工具,用来检查你的代码是否符合指定的规则(你和你的团队可以自行约定一套规则)。在创建项目时,我们使用的是 JavaScript Standard Style 代码风格的规则

2.2 手动修改对照文档

打开 ESLint 规则表,使用页面搜索(Ctrl + F)这个代码,查找对该规则的一个释义。

2.3 通过插件修改

特点:

eslint会自动高亮错误显示

通过配置,eslint会自动帮助我们修复错误

配置:

eslint的配置文件必须在根目录下,这个插件才能才能生效  

加入以下代码:

// 当保存的时候,eslint自动帮我们修复错误
"editor.codeActionsOnSave": {"source.fixAll": true
},
// 保存代码,不自动格式化
"editor.formatOnSave": false

如果有以下语句记得删除,即自动格式化:

"editor.formatOnSave": true

3 Vuex

3.1 创建仓库

3.1.1 安装Vuex包

安装vuex与vue-router类似,vuex是一个独立存在的插件,如果脚手架初始化没有选 vuex,就需要额外安装

yarn add vuex@3 或者 npm i vuex@3

注意:报错可能是因为脚手架安装的eslint版本太高了,如果使用npm安装,可以在后面添:

npm i vuex@3 --legacy-peer-deps

进行强制安装

安装好后,为了维护项目目录的整洁,可以在src目录下新建一个store目录其下放置一个index.js文件 (和 router/index.js 类似) 


3.1.2 创建仓库

//store/index.js
// 导入 vue
import Vue from 'vue'
// 导入 vuex
import Vuex from 'vuex'
// vuex也是vue的插件, 需要use一下, 进行插件的安装初始化
Vue.use(Vuex)// 创建仓库 store
const store = new Vuex.Store()// 导出仓库
export default store

3.1.3 将仓库挂载到vue实例上

//main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'Vue.config.productionTip = falsenew Vue({render: h => h(App),store
}).$mount('#app')

此刻起, 就成功创建了一个空仓库!!


3.2 仓库中的共享数据与方法 

3.2.1 state状态(数据)

3.2.1.1 提供数据
//store/index.js
// 创建仓库 store
const store = new Vuex.Store({// state 状态, 即数据, 类似于vue组件中的data,// 区别:// 1.data 是组件自己的数据, // 2.state 中的数据整个vue项目的组件都能访问到state: {count: 101}
})

3.2.1.2 访问数据
3.2.1.2.1 $store

 1.Vue模板中获取 this.$store
    模板中:     {{ $store.state.xxx }}
    组件逻辑中:  this.$store.state.xxx
 2.js文件中获取 import 导入 store
    JS模块中:   store.state.xxx

这样写太复杂,可以使用下面的映射方法


 3.2.1.2.2 mapState

第一步:导入mapState (mapState是vuex中的一个函数)(在需要该方法的vue文件中导入) 

import { mapState } from 'vuex'

第二步:采用数组形式引入state属性

mapState(['count']) 

上面这个语句最终得到类似于下面这个结果 

count () {return this.$store.state.count
}

 第三步:利用展开运算符将导出的状态映射给计算属性

  computed: {...mapState(['count'])}

 接下来就相当于conputed计算属性中有了count这个属性,可以直接用了

要区分的是,虽然写在computed中,但state并没有直接修改数据的权利,要使用getters


3.2.1.2 修改数据与严格模式

state中的数据实操上可以直接修改,如下:

<template><div class="box"><h2>Son1 子组件</h2>从vuex中获取的值: <label>{{$store.state.count}}</label><br><button @click="set">值 + 1</button></div>
</template><script>
export default {name: 'Son1Com',methods: {set () {this.$store.state.count++}}
}
</script>

 但并不建议这样做,违背了vuex的单向数据流初衷,我们建议只使用mutations修改数据

通过 配置strict: true 可以开启严格模式,开启严格模式后,直接修改state中的值会报错

//store/index.js
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 200}
})export default store

3.2.2 mutations(同步方法)

3.2.2.1 提供方法
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({strict: true,state: {count: 200},mutations: {// 方法里参数:第一个参数是当前store的state属性// 第二个参数:传递进来的数据,只能传一个,多参数可用对象addCount (state, n) {state.count += n}}
})export default store

3.2.2.2 使用方法
3.2.2.2.1 $store

语法:

this.$store.commit('方法名', 数据)

示例:

<template><div class="box"><h2>Son1 子组件</h2>从vuex中获取的值: <label>{{$store.state.count}}</label><br><button @click="set(1)">值 + 1</button></div>
</template><script>
export default {name: 'Son1Com',methods: {set (num) {this.$store.commit('addCount', num)}}
}
</script>

3.2.2.2.2 mapMutations

与mapState使用步骤相同,此处不再赘述,

注意:

1. mutations为方法而不是state那样的计算属性,因此要放在methods中进行展开

2. 传参直接加括号传即可,因为...mapMutations(['addCount'])等效于

addCount (n) {this.$store.commit('addCount', n)
}

示例: 

<template><div class="box"><h2>Son2 子组件</h2>从vuex中获取的值:<label>{{count}}</label><br /><button @click="addCount(-1)">值 - 1</button></div>
</template><script>
import { mapState, mapMutations } from 'vuex'export default {name: 'Son2Com',//computed: {//...mapState(['count'])//},methods: {...mapMutations(['addCount'])}
}
</script>

注意:Vuex中mutations中要求不能写异步代码,如果有异步的ajax请求,应该放置在actions中


3.2.3 actions(异步方法)

3.2.3.1 提供方法 

示例:1s后修改数据 

import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({//...mutations: {addCount (state, n) {state.count += n}},actions: {setAsyncCount (context, num) {    //context在模块中理解,此处就当作是store仓库setTimeout(() => {context.commit('addCount', num) //actions不能直接修改state中的数据,需要调用mutations进行修改}, 1000)}}
})export default store

3.2.3.2 使用方法
3.2.3.2.1 $store
<template><div class="box"><h2>Son1 子组件</h2>从vuex中获取的值: <label>{{$store.state.count}}</label><br><button @click="set(1)">值 + 1</button></div>
</template><script>
export default {name: 'Son1Com',methods: {set (num) {this.$store.dispatch('setAsyncCount', num)}}
}
</script>

3.2.3.2.2 mapActions

与mapMutations使用方法类似,不再赘述

<template><div class="box"><h2>Son2 子组件</h2>从vuex中获取的值:<label>{{count}}</label><br /><button @click="setAsyncCount(-1)">值 - 1</button></div>
</template><script>
import { mapState, mapMutations, mapActions } from 'vuex'export default {name: 'Son2Com',computed: {...mapState(['count'])},methods: {...mapMutations(['addCount']),...mapActions(['setAsyncCount'])}
}
</script>

等价:

methods: {setAsyncCount (n) {this.$store.dispatch('setAsyncCount', n)},

3.2.4 getters(计算数据)

3.2.4.1 提供计算数据
const store = new Vuex.Store({//...getters: {// getters函数的第一个参数是 state// 必须要有返回值filterList (state) {return state.list.filter(item => item > 5)}// 简写:// filterList: state => state.list.filter(item => item > 5)}
})

3.2.4.2 使用计算数据
3.2.4.2.1 $store

与state一样 

<div>{{ $store.getters.filterList }}</div>

 3.2.4.2.2 mapGetters
computed: {...mapGetters(['filterList'])
}
 <div>{{ filterList }}</div>

3.2.5 总结


3.3 module模块化

3.3.1 提供数据/方法

写法与前文中一样,只不过把实例化对象内部的state、mutations、actions、getters对象抽离出放在单独个js文件中,再导出,最后再在实例化对象中的module对象上挂载即可

示例:定义两个模块user、setting

user: 

//modules/user.js
const state = {userInfo: {name: 'zs',age: 18}
}const getters = {// 分模块后,state指代子模块的stateUpperCaseName (state) {return state.userInfo.name.toUpperCase()}
}//默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块
const mutations = {setUser (state, newUserInfo) {state.userInfo = newUserInfo}
}const actions = {setUserSecond (context, newUserInfo) {// 将异步在action中进行封装setTimeout(() => {// 调用mutation   context上下文,默认提交的就是自己模块的action和mutationcontext.commit('setUser', newUserInfo)}, 1000)}
}export default {namespaced: true, //开启命名空间state,mutations,actions,getters
}

setting:

// modules/setting.jsconst mutations = {setTheme (state, newTheme) {state.theme = newTheme}
}const actions = {}const getters = {}export default {
//官方推荐在模块化中,state以方法的形式进行书写,原因与data一样state () {return {theme: 'dark',desc: '描述真呀真不错'}},mutations,actions,getters
}

在store/index.js文件中的modules配置项中,注册这两个模块

import user from './modules/user'
import setting from './modules/setting'const store = new Vuex.Store({modules:{user,setting}
})

 3.3.2 访问数据/方法

3.3.2.1 打印对比是否开启命名空间对$store中属性的影响 

红色框:cart组件内的数据与方法

蓝色框: 全局的数据与方法

未开启命名空间:

开启命名空间:

 


3.3.2.2 未开启命名空间

未开启命名空间时,模块中的数据/方法存在时的变量名称与位置和全局数据/方法一样,

因此获取数据/方法的步骤语法也完全一样,此处就不再过多赘述,直接列出:

xxx代表数据/方法变量名,yyy代表模块名,n代表参数,组件逻辑指的是vue文件script内,模板指的是vue文件template内部标签中

mapxxx组件逻辑中直接使用模板中直接使用JS文件中
statemapState(['yyy'])this.$store.state.yyy.xxx$store.state.yyy.xxxstore.state.yyy.xxx
gettersmapGetters(['xxx'])this.$store.getters.xxx$store.getters.xxxstore.getters.xxx
mutationsmapMutations(['xxx'])this.$store.commit('xxx', n)$store.commit('xxx', n)store.commit('xxx', n)
actionsmapActions(['xxx'])this.$store.dispatch('xxx', n)$store.dispatch('xxx', n)store.dispatch('xxx', n)

注意:不需要死记硬背,观察3.3.4.1中的位置与名称即可

1.mapXXX(['aaa', 'bbb'])可以同时映射多个,开启命名空间时也同理

2.无论是否开启命名空间,只要写在模块中,state中的数据就会被套一层模块名,

因此要用mapState(['yyy'])

3.mapxxx使用前要引入,如 import { mapxxx } from 'vuex'

4.state、getters的mapxxx要在computed中进行展开,而mutations与actions的则要在methods中

5.展开之后相当于直接给computed/methods添加了同名的数据/方法,使用方法与事项与不使用vuex时的一样

6.在js中使用前要引入,如 import store from '@/store/index.js'

7.mutations与actions中的参数只能传一个,要传多个需要用数组或对象


3.3.2.3 开启命名空间

开启命名空间时,除了state保持不变,其他三类的数据/方法名都会被加上 模块名/ ,但本质使用方法仍不变

因此直接把原本的xxx替换为yyy/xxx即可,除此之外mapxxx还增加了一种写法,见下表 

mapxxx组件逻辑中直接使用模板中直接使用
state

mapState(['yyy'])

mapState('yyy', ['xxx'])

this.$store.state.yyy.xxx$store.state.yyy.xxx
getters

mapGetters(['yyy/xxx'])

mapGetters('yyy', ['xxx'])

this.$store.getters.['yyy/xxx']$store.getters.['yyy/xxx']
mutations

mapMutations(['yyy/xxx'])

mapMutations('yyy', ['xxx'])

this.$store.commit('yyy/xxx', n)$store.commit('yyy/xxx', n)
actions

mapActions(['yyy/xxx'])

mapActions('yyy', ['xxx'])

this.$store.dispatch('yyy/xxx', n)$store.dispatch('yyy/xxx', n)

注意:

1.由于篇幅原因,我删除了js这一列,但其也一样,将xxx改为yyy/xxx即可

2.记得加[''],因为yyy/xxx是一个整体作为变量名


 4 json-server——模拟服务端api

4.1 使用步骤 

第一步:安装全局工具 json-server (全局工具仅需要安装一次)

yarn global add json-server 或 npm i json-server  -g

第二步:新建一个.json文件

推荐在vue等项目根目录中新建一个db文件夹,再在其中创建一个index.json文件

.json文件书写示例:

{"cart": [{"id": 100001,"name": "低帮城市休闲户外鞋天然牛皮COOLMAX纤维","price": 128,"count": 1,"thumb": "https://yanxuan-item.nosdn.127.net/3a56a913e687dc2279473e325ea770a9.jpg"},{"id": 100002,"name": "网易味央黑猪猪肘330g*1袋","price": 39,"count": 10,"thumb": "https://yanxuan-item.nosdn.127.net/d0a56474a8443cf6abd5afc539aa2476.jpg"},{"id": 100003,"name": "KENROLL男女简洁多彩一片式室外拖","price": 128,"count": 2,"thumb": "https://yanxuan-item.nosdn.127.net/eb1556fcc59e2fd98d9b0bc201dd4409.jpg"},{"id": 100004,"name": "云音乐定制IN系列intar民谣木吉他","price": 589,"count": 1,"thumb": "https://yanxuan-item.nosdn.127.net/4d825431a3587edb63cb165166f8fc76.jpg"}],"friends": [{ "id": 1, "name": "zs", "age": 18 },{ "id": 2, "name": "ls", "age": 19 },{ "id": 3, "name": "ww", "age": 20 }]
}

第三步:进入 db 目录,执行命令,启动后端接口服务

使用--watch 参数 可以实时监听 json 文件的修改

json-server  --watch  index.json

4.2 使用语法

4.2.1 获取数据

axios.get('http://localhost:3000/cart')

4.2.2 修改数据

axios.patch(`http://localhost:3000/cart/${obj.id}`, {count: obj.newCount})

要修改哪个值就在对象中传哪个值

更多使用方法见 json-server - npm


http://www.mrgr.cn/news/94492.html

相关文章:

  • 【深度学习与大模型基础】第4章-矩阵的运算
  • Linux(2025.3.14)
  • C++前缀和
  • 【亲测有用】数据集成平台能力演示(支持国产数据库DaMeng与KingBase)
  • CNN 稠密任务经典结构
  • 多线程(超详细) (ε≡٩(๑>₃<)۶ 一心向学)
  • 16.使用读写包操作Excel文件:XlsxWriter 包
  • 《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现
  • Java入职篇(1)——心态篇
  • Java面试:集合框架体系
  • 安装 Powerlevel10k 及 Oh My Zsh 的使用
  • macOS 终端优化
  • MySQL中的B+树索引经验总结
  • 嵌入式八股ARM篇
  • 多线程与并发编程 面试专题
  • HarmonyOS NEXT - 电商App实例三( 网络请求axios)
  • MFC控件按钮的使用
  • Docker 》》Docker Compose 》》network 网络 compose
  • 保姆级离线TiDB V8+解释
  • STAR Decomposition 一种针对极端事件的信号分解方法 论文精读加复现