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

【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 = false

new 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指代子模块的state
  UpperCaseName (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和mutation
      context.commit('setUser', newUserInfo)
    }, 1000)
  }
}


export default {
  namespaced: true, //开启命名空间
  state,
  mutations,
  actions,
  getters
}

setting:

// modules/setting.js

const 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.kler.cn/a/588444.html

相关文章:

  • CSS3学习教程,从入门到精通,CSS3 文字样式语法知识点及案例代码(7)
  • 消息队列的特性与使用场景:Kafka、ActiveMQ、RabbitMQ与RocketMQ的深度剖析
  • 图论之cruskal算法(克鲁斯卡尔)
  • Bash语言的进程管理
  • 数字化转型 - 数据驱动
  • 出现缓存雪崩、缓存穿透、缓存预热、缓存更新和缓存降级的场景,以及如何解决
  • 【数据结构与算法】Java描述:第四节:二叉树
  • DVWA 命令注入从 Low 到 Impossible 教程及源码分析
  • 监控易对各类服务器硬件的广泛支持和深入监控能力
  • pybind11出现的问题
  • 每天五分钟深度学习框架pytorch:常见神经网络层的维度信息总结
  • Linux mount和SSD分区
  • 垃圾回收机制是什么 ?JVM 核心结构?
  • Linux-进程概念
  • 麒麟服务器操作系统Sqlite部署手册
  • 笔记:代码随想录算法训练营day48:739. 每日温度\496.下一个更大元素 I\503.下一个更大元素II
  • 【专项测试】限流测试
  • Java算法OJ(12)
  • Vue 3 组件库主题化与可扩展性深度剖析:设计模式与实现策略 - 构建灵活适应多场景的组件库架构
  • Java缓存String(字符串常量池)、Integer (-128 到 127 )