前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅学前端:Vue篇(四)

浅学前端:Vue篇(四)

原创
作者头像
传说之下的花儿
发布2023-11-14 11:13:39
1580
发布2023-11-14 11:13:39
举报

3) Vuex

1. 入门

学习前先看这个需求,我先在有两个组件,一个是外面的主页,一个是里面的p1,p1里有个文本框,需求是在文本框里修改用户姓名,修改完后希望修改后的姓名显示到主页那里,欢迎xxx:

这个需求如何实现呢,用以前的办法就不好实现了,以前的办法是你这个文本框是属于p1组件的,只能和p1组件里的data()返回的数据对象进行绑定,没办法直接被主页这个组件访问到。

根据这个需求,我们就需要学习一个新的技术了——vuex。

这个问题本质上是一个数据共享的问题,我们可以给这两个组件找一个可以数据共享的地方,一个组件往里存数据,另一个从里面取数据。

有人可能说了,我们可以用上面刚刚学到的localStoragesessionStorage,p1组件点击确定之后,可以将用户姓名存到比如说sessionStorage里,再让主页从里面取出修改后的用户名不就可以啦?

vuex 可以在多个组件之间共享数据,并且共享的数据是【响应式】的,即数据的变更能及时渲染到模板。

  • 与之对比 localStorage 与 sessionStorage 也能共享数据,但缺点是数据并非【响应式】

与vuex相关的代码在src/store/index.js里:

代码语言:javascript
复制
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

首先需要定义 state 与 mutations 他们一个用来读取共享数据,一个用来修改共享数据

src/store/index.js

代码语言:javascript
复制
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// 这里我们就可与来定义共享数据

/*
  读取数据,走 state, getters
  修改数据,走 mutations, actions
*/
// 从state读取共享数据,在mutations修改共享数据
export default new Vuex.Store({
  // 共享数据的位置
  state: {
    name: '',
  },
  getters: {
  },
  // 如果需要修改共享位置,不可以直接修改state里的内容,需要在mutations里添加方法
  mutations: {
    updateName(state, newName) {
      state.name = newName;
    },
  },
  actions: {
  },
  modules: {
  }
})

修改共享数据

代码语言:javascript
复制
<template>
    <div class="p">
        p1
        <el-input placeholder="请修改用户名" v-model="name"></el-input>
        <el-button type="primary" v-on:click="updateName()">修改</el-button>
    </div>
</template>
<script>
export default {
    data() {
        return {
            name: ''
        }
    },
    methods: {
        updateName() {
            // 修改共享数据
            // mutations 方法不能直接调用,只能通过 `store.commit(mutation方法名, 参数)` 来间接调用
            this.$store.commit('updateName', this.name);
        },
    }
}
</script>
<style scoped>
...
</style>
  • mutations 方法不能直接调用,只能通过 store.commit(mutation方法名, 参数) 来间接调用

读取共享数据

代码语言:javascript
复制
<template>
    <div class="container">
        主页
        <el-container>
            <el-header>
                <div class="t">欢迎您:{{this.$store.state.name}}</div>
            </el-header>
            <el-container>
                <el-aside width="200px"></el-aside>
                <el-main>
                    <!-- 占位 -->
                    <router-view></router-view>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>
<script>
export default {
    data() {
        return {}
    },
}
</script>
<style scoped>
    ...
</style>
2. mapState

作用:根据state里的属性,自动生成计算属性 name(){ return this.$store.state.name }

每次去写 $store.state.name 这样的代码显得非常繁琐,可以使用计算属性来简化代码:

代码语言:javascript
复制
<template>
。。。
                <div class="t">欢迎您:{{name}}</div>
。。。
</template>
<script>
export default {
    data() {
        return {}
    },
    computed: {
        name() {
            return this.$store.state.name
        },
    }
}
</script>
<style scoped>
...
</style>

如果我们还有一个age数据需要共享,那么还需要在computed里写一个age()...

可以用 vuex 帮我们生成计算属性:

src/views/example16/ContainerView.vue

代码语言:javascript
复制
...
<script>
import { mapState } from "vuex"
console.log(mapState(['name', 'age']))
....

可以看到mapState为我们已经生成了对应计算属性了,那么就不需要在computed里写计算属性了:

代码语言:javascript
复制
<template>
    <div class="container">
        主页
。。。
                <div class="t">欢迎您:{{name}}{{age}}</div>
。。。
</template>
<script>
import { mapState } from "vuex"
export default {
    data() {
        return {}
    },
    // computed: {
    //     name() {
    //         return this.$store.state.name;
    //     },
    //     age() {
    //         return this.$store.state.age;
    //     }
    // }
    
    computed: mapState(['name', 'age']),
    // 等价的写法:... 展开运算符,相当于展开后又塞入了一个空对象里
    // computed: {
    //     ...mapState(['name', 'age'])
    // }
}
  • mapState方法 返回的是一个对象,对象内包含了 name() 和 age() 的这两个方法作为计算属性
3. mapMutations

作用: 根据mutatinos里的属性方法,生成类似于这种形式的代码: updateName() { this.$store.commit('updateName', this.name); },

刚才我们使用了vuex给我们提供的mapState函数帮我们生成了计算属性,算是对我们读取共享数据的一种优化。

那我们来看修改共享数据,原本是我们自己写了个updataName方法来修改共享数据,那么可以可以也有优化呢?

答案是可以的,也可以让vuex帮我们生成好:

代码语言:javascript
复制
<script>
import { mapMutations } from 'vuex'
// mapMutations()
console.log(mapMutations(['updateName']))

代码语言:javascript
复制
<template>
    <div class="p">
        p1
        <el-input placeholder="请修改用户名" v-model="name"></el-input>
        <!-- 注意,这里的事件要绑定mapMutations生成的方法名,且需要传入一个参数(作为修改的值) -->
        <el-button type="primary" v-on:click="updateName(name)">修改</el-button>
    </div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
    data() {
        return {
            name: ''
        }
    },
    mounted: function () {
        this.name = this.$store.state.name;
    },
    methods: {
        // updateName() {
        //     // 修改共享数据
        //     // mutations 方法不能直接调用,只能通过 `store.commit(mutation方法名, 参数)` 来间接调用
        //     this.$store.commit('updateName', this.name);
        // },

        ...mapMutations(['updateName'])
    }
}
</script>
<style scoped>
.p {
    background-color: rgb(165, 150, 242);
    width: 80%;
    height: auto;
    margin: 50px;
}
</style>
  • mapMutations返回的对象中包含的方法,就会调用 store.commit()来执行 mutation 方法
  • 注意参数传递略有不同
4. actions

https://www.bilibili.com/video/BV1Tt4y1772f/?p=94&spm_id_from=pageDriver&vd_source=75d41aa86db8ae1e26da90b1ac6488db&t=38.2

mutations 方法内不能包括修改不能立刻生效(

例如:

代码语言:javascript
复制
 mutations:{
     async updateServerUser(state){
         const resp = await axios.get('/api/user');
         const {name,age} = resp.data.data;
         state.name= name;
         state.age = age;
     }
 }

错误的用法,如果在mutations方法包含了异步操作,会造成开发工具的不准确

)的代码,否则会造成 Vuex 调试工具工作不准确,必须把这些代码写在 actions 方法中

代码语言:javascript
复制
 import Vue from 'vue'
 import Vuex from 'vuex'
 ​
 Vue.use(Vuex)
 ​
 /*
   读取数据,走 state, getters
   修改数据,走 mutations, actions
 */
 import axios from '@/util/myaxios'
 export default new Vuex.Store({
     state: {
         name: '',
         age: 18
     },
     getters: {
     },
     mutations: {
         updateName(state, name) {
             state.name = name;
         },
         // 错误的用法,如果在mutations方法中包含了异步操作,会造成开发工具不准确
         /* async updateServerName(state) {
       const resp = await axios.get('/api/user');
       const {name, age} = resp.data.data;
       state.name = name;
       state.age = age;
     } */
         updateServerName(state, user) {
             const { name, age } = user;
             state.name = name;
             state.age = age;
         }
     },
     // 拿到响应之后,再间接
     actions: {
         async updateServerName(context) {
             const resp = await axios.get('/api/user');
             // 通过commit来定执行那个mutaition
             // 参数1:要执行的mutation的名字
             // 参数2:数据
             context.commit('updateServerName', resp.data.data)
         }
     },
     modules: {
     }
 })
  • 首先应当调用 actions 的 updateServerName 获取数据
  • 然后再由它间接调用 mutations 的 updateServerName 更新共享数据

页面使用 actions 的方法可以这么写

代码语言:javascript
复制
<template>
    <div class="p">
        <el-button type="primary" size="mini"
            @click="updateServerName()">从服务器获取数据,存入store</el-button>
    </div>
</template>
<script>
import { mapActions } from 'vuex'
const options = {
    methods: {
        ...mapActions(['updateServerName'])
    }
}
export default options;
</script>
  • mapActions 会生成调用 actions 中方法的代码
  • 调用 actions 的代码内部等价于,它返回的是 Promise 对象,可以用同步或异步方式接收结果 // 不使用mapActions的写法: export default { methods:{ updateServerName(){ // this.$store.dispatch("action名称"[,参数]); this.$store.dispatch("updateServerName"); }, }, }

总结: 立刻生效的数据才可以使用mutation修改,不是立刻能获取到的数据,就需要使用actions中转一下,间接调用mutations。

5. 小结

vuex说白了就是在组件之间共享数据的,他共享的数据有一个特点,是响应式的;

  • 读取数据:
    • 访问store的state属性,可以使用mapState帮我们生成一些计算属性 import {mapState} from 'vuex'
    • 访问store的getter属性,和上面这个差不多。
  • 修改数据:
    • 使用mutations: 可以使用mapMutations替我们生成一些方法,通过调用这些方法,去修改state里的数据 import {mapMutations} from 'vuex'
    • 使用actions: 可以使用mapActions替我们生成一些方法,通过调用这些方法,间接的调用mutations里的方法,从而修改state里的数据。 import {mapActions} from 'vuex'
    • 具体使用那种,就看你这个数据是否包含了异步操作,没有包括就使用mutation,包括就使用actions。

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3) Vuex
    • 1. 入门
      • 2. mapState
        • 3. mapMutations
          • 4. actions
            • 5. 小结
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档