欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue中的状态管理vuex(一)

程序员文章站 2024-02-28 21:48:46
...

最近一直,在搞mpvue,发现vue中为我们提供的vuex这个状态管理是多么的好用,所以就拿出来和大家分享一下,

一 什么是vuex
Vuex 是一个专门为 Vue.js 应用所设计的集中式状态管理架构。它借鉴了 Flux 和Redux 的设计思想,但简化了概念,并且采用了一种为能更好发挥 Vue.js 数据响应机制而专门设计的实现。
小提示,我们在写vuex的时候只要记住下面这个图的过程和原理就可以了。
vue中的状态管理vuex(一)
我来简单的介绍一下vuex的工作流程。
假设我们这里有home.vue文件
home.vue

        <div id="app">
            <button @click="add">+</button>
        </div>//页面上有一个按钮

当我们点击button按钮,触发add这个点击事件,它是这样工作的,
1)通过$store.dispatch(“自定义名称”,”你想要传递的参数”)发送到actions

            new Vue({
                el:"#app",
                methods:{
                    add(){
                        this.$store.dispatch("addEvent",1)//第一步
                    }
                }
            })

2)actions接收到传递过来的addEvent后,通过commit(“自定义名称”,”参数”)方法传递到mutations

        addEvent(ctx,num){
                ctx.commit("addEvent",num)//这里的addEvent,
                必须与actions提交
                过来的名
            }

3)mutations接收到actions到的数据,在编写以下的代码,

addEvent(state,num){

            }

要记住是在mutations中修改state中的值。

二) 实例 利用vuex实现的本地存储的留言板
留言板可以说是一个比较经典的入门案例,我们尝试着利用vuex和HTML5中localstroage来实现
目录结构
vue中的状态管理vuex(一)

我在components下面创建了一个page,下面的组件都是Home.vue中映射出来。
Home.vue

<template>
    <div>
        <HomeHeader></HomeHeader>
        <HomeAdd></HomeAdd>
        <HomeList></HomeList>
        <tips></tips>
    </div>
</template>

<script>
    import HomeHeader from "./page/Header"
    import HomeAdd from "./page/add"
    import HomeList from "./page/list"
    import tips from "./page/tips"
    export default {
        name:"Home",
        components:{
            HomeHeader,
            HomeAdd,
            HomeList,
            tips
        }
    }
</script>

<style>
</style>

add.vue

<template>
    <div class="container">
        <div class="event-add">
            <input type="text" class="n-input" placeholder="待办事项" v-model="content" />
            <button class="add-btn" @click="add">提交</button>
        </div>
    </div>
</template>

<script>
    export default {
        name:"add",
        data(){
            return {
                content:""
            }
        },
        methods:{
            add:function(){
                var obj={
                    content:this.content,
                    id:0
                }

                this.$store.dispatch("addEvent",obj)
                this.content=""
            }
        }
    }
</script>

<style scoped="scoped">
    .container{
        width: 100%;
        padding: 0 10px;
        max-width: 800px;
        margin: auto;
        box-sizing: border-box;
    }
    .event-add{
        position: relative;
        padding: 30px 90px 30px 0;
        font-size: 16px;
    }
    .event-add .n-input{
        width: 100%;
        height: 40px;
        padding: 7px 10px;
        line-height: 26px;
        border: 1px solid #c0ccda;
        box-sizing: border-box;
        border-radius: 4px;
    }
    .event-add .n-input:focus{
        outline: none;
    }
    .event-add .add-btn{
        position: absolute;
        right: 0;
        top: 30px;
        width: 80px;
        height: 40px;
        line-height: 26px;
        color: #fff;
        outline: none;
        border: 1px solid #00d1b2;
        background: #00d1b2;
    }
</style>

Header.vue

<template>
    <header class="home_header">
        <h1>记事本
            <a class="t-btn">
                <span></span>

            </a>
        </h1>
    </header>
</template>

<script>
    export default {
        name:"HomeHeader"
    }
</script>

<style scoped="scoped">
    header{
        position: relative;
        width: 100%;
        height: 70px;
        z-index: 100;
        background: #00d1b2;

    }
    header h1{
        position: relative;
        width: 100%;
        max-width: 800px;
        margin: 0 auto;
        line-height: 70px;
        text-align: center;
        color: #fff;
        font-size:2rem;
        font-weight: bold;
    }
    header h1 a.t-btn{
        position: absolute;
        right: 10px;
        top: 22px;
        width: 30px;
        height: 26px;
        cursor: pointer;
    }
    header h1 span:before{
        top: 11px;
    }
    header h1 span:after{
        top: 22px;
    }
    header h1 span,header h1 span:before,header h1 span:after{
          position: absolute;
          left:0;
          width:30px;
          height:4px;
          content: '';
          background: #fff;
    }
</style>

list.vue

<template>
    <div class="event-content">
        <div class="event-tab">
            未完成{{noDone}}
            <span class="col-span"></span>
        </div>
        <div class="event-box">
            <div class="event-list" v-for="(item,index) in list" :key="index">
                <input type="checkbox" @click="itemDone(item)" :key="item.id" />
                <div>{{item.content}}</div>
                <button class="cancel-btn" @click="canel(index)">删除</button>
            </div>

        </div>

        <div class="event-tab">
            完成{{done}}
            <span class="col-span"></span>
        </div>
        <div class="event-box">
            <div class="event-list" v-for="(item,index) in doneList" :key="index">
                <div>{{item.content}}</div>
            </div>

        </div>


    </div>
</template>

<script>
    export default {
        name:"List",
        computed:{
            list(){
                return this.$store.getters.list
            },
            noDone(){
                return this.$store.getters.noDone
            },
            done(){
                return this.$store.getters.done
            },
            doneList(){
                return this.$store.getters.doneList
            }
        },
        methods:{
            canel:function(i){
                this.$store.dispatch("canelEvent",i)
            },
            itemDone:function(obj){
//              console.log(index)
                this.$store.dispatch("itemDone",obj)
//              this.$store.dispatch("getShow",)
//              this.selected = false
            }
        },
        data(){
            return {
//              selected:false
            }
        }
    }
</script>

<style scoped="scoped">
    ul li{
        list-style: none;
        padding: 0;
        margin: 0;
    }
    .event-content{
        width: 100%;
        padding: 0 10px;
        max-width: 800px;
        margin: auto;
        box-sizing: border-box;
    }
    .event-content .event-tab{
        position: relative;
        height: 44px;
        line-height: 44px;
        padding-left:20px;
        border-bottom:1px solid #fff;
        box-sizing: border-box;
        color: #fff;
        cursor:pointer;
        background: #00d1b2;
    }
    .event-content .event-tab span{
        position: absolute;
        right: 20px;
        top: 15px;
        width: 10px;
        height: 10px;
        content: "";
        border-top: 2px solid #fff;
        border-right: 2px solid #fff;
        transform: rotate(45deg);
        transition: transform .3s;
    }
    .event-content .event-box{
        list-style: none;
        overflow: hidden;
        border-left:1px solid #eee;
        border-right:1px solid #eee;
        transition: height .3s;
        display: block;
        height: auto;
    }
    .event-content .event-box .event-list{
            position: relative;
            min-height: 44px;
            line-height: 25px;
           padding: 10px 100px 10px 50px;
            box-sizing: border-box;
            border-bottom: 1px solid #eee;
            color: #373e40;
    }

    .event-content .event-box .event-list input[type=checkbox]{
            position: absolute;
        left: 15px;
        top: 12px;
        width: 20px;
        height: 20px;
    }
    .event-content .event-box .event-list .cancel-btn{
            position: absolute;
        right: 10px;
        top: 7px;
        width: 50px;
        height: 30px;
        line-height: 30px;
        padding: 0;
        background: #fff;
        border: 1px solid #c0ccda;
        color: #666;
        font-size: 12px;
        text-align: center;
        border-radius: 4px;
        box-sizing: border-box;
        cursor: pointer;
    }
</style>

tips.vue

<template>
    <div class="tips" id="tips" v-show="isShow">
        <div class="tips-mask" :class="{move:domove}">
            {{msg}}
            <button class="btn btn-danger" @click="queDel">确定</button>
            <button class="btn btn-primary" @click="quxiao">取消</button>
        </div>
    </div>
</template>

<script>
    export default {
        name:"Tips",
        mounted(){
            var _this = this
            this.getSize()
            window.onresize = function(){
                _this.getSize()
            }

        },
        methods:{
            getSize:function(){
                var oTips = document.getElementById("tips")
                var cW = document.documentElement.clientWidth
                if(cW>375){
                    var cH = document.documentElement.clientHeight
                    oTips.style.height = cH+"px"
                }else{
                    var cH = document.body.clientHeight
                    oTips.style.height = cH+"px"
                }
            },
            queDel:function(){
                this.$store.dispatch("cancel")
            },
            quxiao:function(){
                this.$store.dispatch("quxiao")
            }
        },
        data(){
            return {
                msg:"你确定要删除吗?!",
                domove:false
            }
        },
        computed:{
            isShow(){
                return this.$store.getters.show
            }
        }

    }
</script>

<style scoped="scoped">
    .tips{
        width: 100%;
        position: absolute;
        left: 0;
        top: 0;
        bottom: 0;
        z-index:100;

    }
    .tips .tips-mask{
        width: 200px;
        margin: 0 auto;
        background:;
        /*height: 120px;*/
        position: relative;
        background:rgba(0,0,0,0.5);
        border-radius:4px;
        transform: translate(0px,20px);
        transition: transform 0.5s;
        padding: 10px 15px;
        color: #fff;
        text-align: center;
        line-height: 40px;
        z-index:99999
    }
    .tips .tips-mask.move{
        transform: translate(0px,120px);
    }
</style>

store/index.js

import Vue from 'vue'
import Vuex from "vuex"

Vue.use(Vuex)
const state = {
    listArr:localStorage["listArr"]?JSON.parse(localStorage["listArr"]):[],
    doneArr:localStorage["doneArr"]?JSON.parse(localStorage["doneArr"]):[],
    count:0,
    show:false,
    index:0
}
const mutations = {
    addEvent(state,obj){
        state.count++
        obj.id = state.count
        state.listArr.push(obj)
        localStorage.setItem("listArr",JSON.stringify(state.listArr))
    },
    canelEvent(state,i){
        state.index = i
        state.show = !state.show 
    },
    itemDone(state,obj){
        for (var j=0;j<state.listArr.length;j++) {
            if(state.listArr[j].id===obj.id){
                var item = state.listArr[j]
                state.listArr.splice(j,1)
                break;
            }
        }
        state.doneArr.push(item)
        localStorage.setItem("doneArr",JSON.stringify(state.doneArr))
        localStorage.setItem("listArr",JSON.stringify(state.listArr))
    },
    isShow(state,isShow){
        state.show = isShow
    },
    cancel(state){
        state.listArr.splice(state.index,1)
        state.show = !state.show
        localStorage.setItem("listArr",JSON.stringify(state.listArr))
    },
    quxiao(){
        state.show = false
    }
}
const actions = {
    addEvent(ctx,obj){
        ctx.commit("addEvent",obj)
    },
    canelEvent(ctx,i){
        ctx.commit("canelEvent",i)
    },
    itemDone(ctx,obj){
        ctx.commit("itemDone",obj)
    },
    getShow(ctx,isShow){
        ctx.commit("isShow",isShow)
    },
    cancel(ctx){
        ctx.commit("cancel")
    },
    quxiao(ctx){
        ctx.commit("quxiao")
    }
}
const getters = {
    list(){
        return state.listArr
    },
    noDone(){
        return state.listArr.length
    },
    done(){
        return state.doneArr.length
    },
    doneList(){
        return state.doneArr
    },
    show(){
        return state.show
    }
}



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

这里的vuex我并没有做目录分解,也是为了方便大家观看
完成效果图
vue中的状态管理vuex(一)
vue中的状态管理vuex(一)
vue中的状态管理vuex(一)
我下次会给大家带来,我会介绍一下这个案例,如何做前后端分离的效果,以及如何在vue-cli中访问php的后端接口。