Vuex —— Day1

vuex概述

vuex是vue的状态管理工具,可以帮我们管理vue通用 的数据(多组件共享的数据)

vuex的应用场景:

  • 某个状态在很多个组件中都会使用(eg.个人信息)
  • 多个组件共同维护一份数据(eg.购物车)

如果没有vuex,当我们遇到一些通用数据的场景,那原本的数据传递就会是:子传父、父传子;中间会经历大量的组件通信

但有了vuex之后,通用数据直接存到仓库里,将来任何组件都可以直接拿来用

优势:

  • 共同维护一份数据,数据集中化管理
  • 响应式变化 ------ 任何一个组件对数据进行了修改,一旦vuex里的数据变化了,所有用到这个数据的地方都会立刻响应式更新

构建vuex多组件数据共享环境

目标:实现三个组件共享同一份数据 ------ 任一组件都可修改数据;三个组件的数据同步

创建项目:vue create vuex-demo

其余

创建三个组件:(components文件夹下)App.vue、Son1.vue、Son2.vue

App.vue

html 复制代码
<template>
  <div id="app">
    <h1>根组件</h1>
    <input type="text">
    <Son1></Son1>
    <hr>
    <Son2></Son2>
  </div>
</template>

<script>
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'

export default {
  name: 'app',
  data: function () {
    return {

    }
  },
  components: {
    Son1,
    Son2
  }
}
</script>

<style>
#app {
  width: 600px;
  margin: 20px auto;
  border: 3px solid #ccc;
  border-radius: 3px;
  padding: 10px;
}
</style>

Son1.vue

html 复制代码
<template>
  <div class="box">
    <h2>Son1 子组件</h2>
    从vuex中获取的值: <label></label>
    <br>
    <button>值 + 1</button>
  </div>
</template>

<script>
export default {
  name: 'Son1Com'
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

Son2.vue

html 复制代码
<template>
  <div class="box">
    <h2>Son2 子组件</h2>
    从vuex中获取的值:<label></label>
    <br />
    <button>值 - 1</button>
  </div>
</template>

<script>
export default {
  name: 'Son2Com'
}
</script>

<style lang="css" scoped>
.box {
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

创建一个空仓库

目标:安装vuex插件,初始化一个空仓库

步骤:

  • 安装vuex

yarn add vuex@3

  • 新建vuex模块文件

store/index.js 专门用于存放vuex

  • 创建仓库

//vuex也是vue的插件, 需要use一下, 进行插件的安装初始化

Vue.use(Vuex)

//创建仓库

new Vuex.Store()

  • main.js导入挂载

挂载到Vue实例上

验证仓库是否建成: this.$store

[vue的this. 常见的用法_vue.js_深度学习研究员-GitCode 开源社区](https://gitcode.csdn.net/66ca114baa1c2020b359bd33.html?dp_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6NjkxODM2LCJleHAiOjE3MzM0ODM1NTksImlhdCI6MTczMjg3ODc1OSwidXNlcm5hbWUiOiJtMF83MzU1Nzk1MyJ9.Y7V93ebqFr08hvFWLFtyD-D6efL61yJgQdNyQJiVyr8&spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~activity-3-139167884-blog-126088266.235%5Ev43%5Epc_blog_bottom_relevance_base6&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~activity-3-139167884-blog-126088266.235%5Ev43%5Epc_blog_bottom_relevance_base6&utm_relevant_index=6 "vue的this. 常见的用法_vue.js_深度学习研究员-GitCode 开源社区")

Vue.js 中,this.$ 用于访问 Vue 实例的一些内置属性、方法或者插件提供的功能

一旦仓库建完后,所有组件都能访问到这个仓库


state状态

  • 提供数据

所有共享的数据都要统一放到Store中的State中存储;在state对象中可以添加我们想要共享的数据

javascript 复制代码
//创建仓库
const store = new Vuex.Store({
    state:{//所有组件共享的数据;区别于data ------ 组件自己的数据
        count:101
    }
})
  • 使用数据

通过store直接访问

获取仓库 ------ this.$store / import 导入 store

使用数据:

模板中:{{$store.state.xxx}}

组件逻辑中:this.$store.state.xxx

JS模块中:store.state.xxx

效果展示:

完整代码:

App.vue

html 复制代码
<template>
  <div id="app">
    <h1>根组件 - {{ $store.state.title }} - {{  $store.state.count }}</h1>
    <input type="text">
    <Son1></Son1>
    <hr>
    <Son2></Son2>
  </div>
</template>

<script>
import Son1 from './components/Son1.vue'
import Son2 from './components/Son2.vue'

export default {
  name: 'app',
  created () {
    console.log(this.$store.state.count)
  },
  data: function () {
    return {

    }
  },
  components: {
    Son1,
    Son2
  }
}
</script>

<style>
#app {
  width: 600px;
  margin: 20px auto;
  border: 3px solid #ccc;
  border-radius: 3px;
  padding: 10px;
}
</style>

main.js

javascript 复制代码
//入口文件;第一个执行的文件;main.js基于App.vue创建结构渲染index.html
import Vue from 'vue'
import App from './App.vue'
import store from '@/store/index'// 导入得到仓库
// 通过仓库访问状态
console.log(store.state.count)

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store
}).$mount('#app')

components/Son1.vue

html 复制代码
<template>
  <div class="box">
    <h2>Son1 子组件</h2>
    从vuex中获取的值: <label>{{ $store.state.count }}</label>
    <br>
    <button>值 + 1</button>
  </div>
</template>

<script>
export default {
  name: 'Son1Com'
}
</script>

<style lang="css" scoped>
.box{
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

components/Son2.vue

html 复制代码
<template>
  <div class="box">
    <h2>Son2 子组件</h2>
    从vuex中获取的值:<label>{{ $store.state.count }}</label>
    <br />
    <button>值 - 1</button>
  </div>
</template>

<script>
export default {
  name: 'Son2Com'
}
</script>

<style lang="css" scoped>
.box {
  border: 3px solid #ccc;
  width: 400px;
  padding: 10px;
  margin: 20px;
}
h2 {
  margin-top: 10px;
}
</style>

store/index.js

javascript 复制代码
// 存放vuex相关的核心代码
import Vue from 'vue'
import Vuex from 'vuex'

// 插件安装
Vue.use(Vuex)

// 创建仓库(空仓库)
const store = new Vuex.Store({
  // 通过state提供所有组件共享的数据
  state: {
    title: '大标题',
    count: 100
  }
})

// 导出给main.js使用
export default store

通过辅助函数

前情:

老在模板里{{$store.state.count}}这么引用太麻烦,考虑使用计算属性:

{{ count }}

computed: {

count() {

return this.$store.state.count

}

},

到底什么是计算属性,为什么要用计算属性?

计算属性 是写在computed对象中的属性 ,本质上是一个方法,不过使用 时仍然当属性使用

计算属性的特点是,响应式更新,当依赖的属性发生变化时,计算属性会自动重新计算并更新其值。这意味着我们不需要手动去监听属性的变化,也不需要手动去更新计算属性的值,Vue 会自动帮我们完成这些操作。

为什么不用插值表达式?

插值表达式虽然可以填入简单运算,但是当表达式变得复杂,或运算结果需要复用多次的时候,使代码的可读性变差。

简化:vuex为我们提供了mapState 辅助函数,用于帮助我们生成计算属性

步骤:

  • 先导入mapState 辅助函数

import {mapState} from 'vuex'

  • 数组方式引入state

mapState(['count'])

mapState()可以传入对象或者数组;并且返回的是一个对象

传入数组:mapState(['name'])

数组中的每个字符串都会被映射为组件的方法

传入对象:(可以对store中的数据进行重命名)

mapState({

rename: state => state.name

})

  • 展开运算符映射

computed:{

**...**mapState(['count'])

}

*1 computed是一个对象,*computed里面用来定义计算属性

2 ...展开运算符:js 展开运算符"..."的常见用法_js ...展开-CSDN博客

在这里属于对象展开运算符,mapState()返回的是一个对象;

  1. const obj1 = { x: 1, y: 2 };

  2. const obj2 = { ...obj1, z: 3 }; // { x: 1, y: 2, z: 3 }

...mapState(['count']) 等价于 count() { return this.$store.state.count },...

computed:{ **...**mapState(['count']) ,... } 等价于

computed:{ count() { return this.$store.state.count },... }

App.vue

Son1.vue

Son2.vue


mutations

作用:用于修改state数据

vuex遵循单向数据流,组件中不能直接修改仓库的数据

这里注意,如果写成this.$store.state.count++是不会报错的,想让它报错(严格遵循单向数据流的形式可以通过 strict:true 开启严格模式

需要让组件把修改要求提交到仓库中,让组件通过提交mutations的方式,让仓库进行修改

步骤:

  • 仓库里(store/index.js)定义mutations对象,对象里存放修改state的方法(即仓库提供方法)
  • 组件中提交调用mutations(组件中调用)

效果展示:

流程:


mutations传参

提交调用mutations函数时是可以传参的

this.$store.commit('xxx', 参数)

需求1:希望 +1、+5、+10可以共用一个方法;而不是写成addOne、addFive、addTen

需求2.改标题

提供方法

提交调用mutations,并传参

效果展示:

注意一个问题

mutation参数有且只能有一个,如果需要多个参数,需要包装成一个对象


mutations练习

需求:实现输入框的值和仓库状态形成双向联动

这里不可以使用v-model;因为vuex遵循单向数据流,组件中不能直接修改仓库的数据

但v-model用在输入框上,就是value属性和input事件的合写

<input :value ="msg2" @input="msg2 = $event.target.value" type="text">

v-bind:value ="msg2"数据变;视图跟着变

v-on:input ="msg2 = $event.target.value" 对输入框进行监听;实现视图变,数据也跟着变

措施:

  • 输入框进行内容渲染:value + 监听输入获取内容@input
  • 仓库封装mutation处理函数(mutation传参)
  • 组件调用传参(commit调用)

相关推荐
麦麦大数据16 分钟前
D027 v2 vue+django+neo4j 基于知识图谱红楼梦问答系统 (新增问关系功能;新增知识节点和关系管理功能,neo4j增删改查功能)
vue.js·django·问答系统·知识图谱·neo4j·图谱管理·neo4j增删改查
Kevin Wang72743 分钟前
解除chrome中http无法录音问题,权限
前端·chrome
vipbic1 小时前
使用Cursor开发Strapi5插件bag-strapi-plugin
前端·ai编程·cursor
专注前端30年1 小时前
【JavaScript】reduce 方法的详解与实战
开发语言·前端·javascript
ikoala1 小时前
Node.js 25 正式发布:性能飙升、安全升级、全面向 Web 靠拢!
前端·面试·node.js
陈振wx:zchen20081 小时前
前端-ES6-11
前端·es6
菜鸟una2 小时前
【瀑布流大全】分析原理及实现方式(微信小程序和网页都适用)
前端·css·vue.js·微信小程序·小程序·typescript
专注前端30年2 小时前
2025 最新 Vue2/Vue3 高频面试题(10月最新版)
前端·javascript·vue.js·面试
Highcharts.js2 小时前
选择合适的组合:如何打造数据可视化的“黄金组合”
javascript·信息可视化·highcharts·交互式图表开发
文火冰糖的硅基工坊3 小时前
[嵌入式系统-146]:五次工业革命对应的机器人形态的演进、主要功能的演进以及操作系统的演进
前端·网络·人工智能·嵌入式硬件·机器人