vuex 初步学习和使用

一、vuex定义

  • Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式,使用插件的形式引进项目中
  • 集中存储和管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
  • 每一个 Vuex 应用的核心就是 store(仓库),new Vue.store({...}),“store”基本上就是一个容器,它包含应用中大部分的状态 (state)

二、vuex有什么用

  • 解决了多个视图依赖于同一状态
  • 解决了来自不同视图的行为需要变更同一状态
  • Vuex则是把组件的共享状态抽取出来,以一个全局单例模式管理
    同时,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,代码变得更结构化、易维护
    以上就是vuex的思想

三、什么时候用

  • SPA 开发大型单页应用 时使用

四、vuex和全局对象的区别

  • Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  • 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用

五、安装和配置

vuex 

1.安装
    npm i vuex --save-dev
2.配置
    导入vue 和 vuex 
    Vue.ues(Vuex)
    定义一个对象存下面的:
        state 数据
        mutations 对应修改数据的方法
            方法的参数里有(state,payload)
            参数里 默认会有一个state,vue自带的
            payload 调用者传的参数
        export default 导出
    导出一个 new Vuex.Store(对象名) 注意这里的严格区分大小写
3.挂载到实例上 main.js
    导入
    放到vue对象里面
4.使用、取值
    取值 this.$store.state.数据名
    用(改) this.$store.commit('函数名',参数) 
  • 配置如下
    src文件夹里面新建store文件夹index.js文件
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

// vuex的配置项
const options = {
    // state(固定) 是用来存放数据的
    state:{
        // 底部组件 显示或不显示
        showFooter:false,
        isLogin:false
    },
    // mutation 用来修改state里的属性值
    mutations:{
        // 放函数方法 函数名对应都是用来更改数据里变量的 参数里 默认会有一个state,vue自带的
        // 改变showFooter的值  payload代表传的参数->调用者传的参数
        SHOWFOOTER(state,payload){
            state.showFooter=payload;
        },
        // 改变登入状态
        ISLOGIN(state,payload){
            state.isLogin = payload;
        }
    }
}

const store = new Vuex.Store(options);
export default store;

// export default new Vuex.store(options);

main.js 里配置

import Vue from "vue";
import router from "./router/index";
import store from './store/index'
new Vue({
  // 引入store
  store,
  router,
  el: "#app",
  render: h => h(App)
}).$mount("#app");

六、小demo应用

  • 显示隐藏
<template>
    <div>
        <h3>个人中心</h3>
        <div v-if="$store.state.isLogin">
            <p>手机尾号5539</p>
            <button @click="logout">退出登陆</button>
        </div>
        <button v-else @click="login">立即登陆</button>
    </div>
</template>

<script>
export default {
    methods: {
        login(){
            this.$store.commit('ISLOGIN',true);
            // 调用store文件下的index.js仓库里的函数并带参数
        },
        logout(){
            this.$store.commit('ISLOGIN',false);
        }
    },
}
// 通过vuex的 $store.commot 方法使用store创库里的方法并传参数过去
</script>

<style>
</style>
  • 父子通信

子组件

<template>
    <div v-show="show">
        <!-- 蒙层 -->
        <div class="pop"></div>
        <div class="box">
            <h3>温馨提示</h3>
            <div class="content">{{msg}}</div>
            <p>
                <button @click="ok">确认</button>
                <button @click="cancel">取消</button>
            </p>
        </div>
    </div>
</template>

<script>
export default {
    props:["msg","show"],
    methods: {
        ok(){
            this.$emit("yes","ok");
        },
        cancel(){
            this.$emit("no","cancel");
        }
    },
}
</script>

<style scoped>
.pop{
    position: fixed;
    background: #000;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    opacity: 0.5;
}
.box{
    display: inline-block;
    position: fixed;
    top: 50%;
    margin-left: -150px;
    margin-top: -100px;
    left: 50%;
    z-index: 2;
    background: #fff;
    padding: 50px 100px;
}
</style>

父组件

<template>
    <div>
        <Dialog :msg="msg" :show="show" @yes="yes" @no="no"/>
        <p>
            <button @click="showDialog">显示弹框</button>
        </p>
    </div>
</template>

<script>
import Dialog from '@/components/Dialog'
export default {
    data() {
        return {
            msg:"你好吗",
            show:false
        }
    },
    components:{
        Dialog
    },
    methods: {
        showDialog(){
            this.show=true;
        },
        yes(data){
            // 关闭弹窗
            this.show = false;
            alert("你点了确定");    
        },
        no(data){
            // 关闭窗口
            this.show = false;
            // todo
            alert("你点击了取消");
        }
    },
}

</script>

<style>
</style>

// 父子通信 子传父 子使用$emit带参调用父的自定义事件
// 父传子 父通过子的props属性传参数

七、项目应用

  • 需求:底部导航栏里有一个是点击之后隐藏底部的
  • 思路-分析 :
    1.在vuex的store仓库(index.js)里,定义一个showFooter变量储存数据false
    然后在index.js下的mutations,这个里面是处理数据对应的方法SHOWFOOTER,
import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

// vuex的配置项
const options = {
    // state(固定) 是用来存放数据的
    state:{
        // 底部组件 显示或不显示
        showFooter:false
    },
    // mutation 用来修改state里的属性值
    mutations:{
        // 放函数方法 函数名对应都是用来更改数据里变量的 参数里 默认会有一个state,vue自带的
        // 改变showFooter的值  payload代表传的参数->调用者传的参数
        SHOWFOOTER(state,payload){
            state.showFooter=payload;
        }
    }
}

const store = new Vuex.Store(options);
export default store;

// export default new Vuex.store(options);

2.然后通过router下的index.js来导入store
3.然后用到路由守卫,beforeEach((to,from,next)=>{next();}) to记录点击后去的路由地址以及信息from记录上一个路由地址及信息 next(); 下一个,执行的意思。
4.通过给路由添加对应的meta然后在meta下添加标题和showFooter,当然在需要隐藏的下面添加就行,当然值得是true。
5.然后if判断to.meta.showFooter判断是否有showFooter以及值是否为true然后通过调用vuex仓库的方法改变 store.commit('SHOWFOOTER',true)传入true参数改变。
6.最后在底部组件里加上v-if="$store.state.showFooter",注意我们上面的所有操作无非只是改变一个数,然后通过数判断true和false最后应用到底部组件上

import Vue from 'vue';
import Router from 'vue-router';
import store from '../store/index';

// 使用Router
Vue.use(Router);


// 快熟下复制一行ctri+shift+下
// 配置路由
const routerList =[
    {
        path:'/film',
        meta:{
            title:'电影',
            showFooter:true
        },
        component: () => import('@/views/film/index')
    },
    {
        path: '/demo',
        meta: {
            title: 'demo',
        },
        component: () => import('@/views/demo/index')
    },
    {
        path:'/movie',
        component:() =>import('@/views/movie'),
        // redirect 重定向 默认显示的组件,
        redirect:'/movie/list',
        children:[
            {
                path: 'list',
                meta:{
                    title:'电影列表',
                    showFooter:true
                },
                component: () => import('@/views/movie/children/list'),
            },
            {
                path: 'xiangqing',
                meta:{
                    title:'电影详情',
                    showFooter:true
                },
                component: () => import('@/views/movie/children/xiangqing'),
            },
        ]
    },
    {
        path: '/comner',
        meta:{
            title:'影院',
            showFooter:true
        },
        component: () => import('@/views/comner/index'),
        redirect: '/comner/list',
        children:[
            {
                path:'list',
                meta:{
                    title:"影院列表",
                    showFooter:true
                },
                component: () => import('@/views/comner/children/list'),
            }
        ]
    },
    {
        path: '/pintuan',
        meta:{
            title:'拼团'
        },
        component: () => import('@/views/pintuan/index')
    },
    {
        path: '/my',
        redirect: '/my/center',
        component: () => import('@/views/my/index'),
        children: [
            {
                path: 'center',
                meta: {
                    title: '个人中心',
                    showFooter: true
                },
                component: () => import('@/views/my/children/center')
            },
        ]
    },
]

const router = new Router({
    routes:routerList
})
// 路由守卫
router.beforeEach((to,from,next)=>{
    document.title=to.meta.title;
    // showFooter的值为true的时候显示底部
    if(to.meta.showFooter){
        store.commit('SHOWFOOTER',true);
    }else{
        store.commit('SHOWFOOTER', false);
    }
    next();
})
export default router;

八、小总结

1.vuex是一对多的关系,一个数据多个人使用,因此达到了跨组件通讯。但一个改了里面的数据其他访问的数据也会发生变化。
2.router.beforeEach方法,路由守卫。里面的属性能更直观的给我们展示当前路由的信息,我们可以根据这个进行判断达到自己想要的效果。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容

  • VUE Vue :数据驱动的M V Vm框架 m :model(后台提供数据),v :view(页面),vM(模板...
    wudongyu阅读 5,368评论 0 11
  • vue-cli搭建项目 确保安装了node与npm 再目标文件夹下打开终端 执行cnpm i vue-cli -g...
    Akiko_秋子阅读 3,211评论 1 22
  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应...
    白水螺丝阅读 4,652评论 7 61
  • 上一章总结了 Vuex 的框架原理,这一章我们将从 Vuex 的入口文件开始,分步骤阅读和解析源码。由于 Vuex...
    你的肖同学阅读 1,767评论 3 16
  • 一定要做个自律的人,按时作息。给强壮的身体提供养分补给。 坚持健身,外练筋骨皮,增加身体的抗压性!
    王家庄农家书屋阅读 632评论 0 0