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

【VUE2】第五期——VueCli创建项目、Vuex多组件共享数据

黑马程序员视频地址: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 开启命名空间


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是一个整体作为变量名

相关文章:

  • 使用GitHub Actions实现Git推送自动部署到服务器
  • Diffie-Hellman协议简单介绍
  • Java入职篇(3)——Linux常用指令
  • Ubuntu上部署Flask+MySQL项目
  • 【C++】每日一练(链表的中间结点)
  • 蓝桥云客 挖矿
  • `gradio save_to_cache permission denied`
  • LeeCode题库第1456题
  • Linux应用:进程的回收
  • 2018年全国职业院校技能大赛高职组-计算机网络应用竞赛竞赛样题C卷
  • springboot+springai调用deepseek实现与大模型对话聊天
  • Log4j2漏洞攻略
  • H.264视频编解码:从原理到应用
  • 【日志队列】log日志实时写入队列,流式输出
  • 【Java 基础(人话版)】进制转换
  • 【区块链】以太坊
  • 什么是云原生?
  • 前端主题切换架构设计方案
  • 蓝耘携手通义万象 2.1 图生视频:开启创意无限的共享新时代
  • 【软设中级】软件设计师中级专题复习:(专题二)程序语言部分
  • 网站建设总体规划包括/惠东seo公司
  • php 个人网站 源码/优化设计七年级上册数学答案
  • 做微网站公司/阿里巴巴国际站
  • 做销售用什么网站/十大放黄不登录不收费
  • 赛车时时彩网站建设/无锡网站服务公司
  • 网站首页设计多少钱/石家庄seo排名公司