vuex和redux

269 阅读2分钟

vuex

可以用在兄弟组件之间传值,并在任意组件内引用

1,

npm install vuex --save

2,

在store.js内

import Vue from 'vue'
import Vuex from 'vuex'
export defaul new Vuex.store({ 有四个属性
1,state(用于数据存储) 例:state:{ count:1, a:2 b:3 }
2,mutations(用于同步数据修改) 例:mutations:{ add(state){ state.count++ } }
可以直接操作state中的数据
3,actions(用于异步数据修改) 例:actions:{ addCount({commit}){ commot('add')//调用同步修改mutation中的方法 } }
不可以直接操作state中的数据,通常调用mutation中的方法
4,getters(计算过滤属性) 例:getters:{ sum(state){ return state.a+state.b//可以方便操作state内的各个属性并返回在组件内调用 } } })

const state:{
    }
const mutations:{
    }
const action:{
    }
const getters:{
    }
export defaul new Vuex.store({
    state,
    mutations,
    action,
    getters
})

3,

在组件内部引用
在script标签内
import { mapState mapMutations , mapActions , mapGetters } from 'vuex' //解构赋值

export default {  
    methods:{
        内部可以引用mapMutations和mapActions内部的函数
    }
    computed:{
        内部可以应用mapState和mapGetter内部的函数或属性
    }
}  

方法一: methods:{ ...mapMutations(['方法名']) addcount(){ this.add()//调用mutation里的方法 } } 方法二: computed:{ ...mapState(['count'])//取出state里的属性count getCount(){ return this.count } 或-------------------------------------------------- getCount(){ return this.$store.state.count } } 方法三: computed:{ mapState({ count:state=>state.count })

4,

在页面中渲染
方法一:
    适用于所有情况
    {{$store.state.count}}
方法二:
    适用于利用设置属性的情况下
    {{getCount}}
方法三:
    适用于不在methods或mutations内设置方法时直接调用store.js中的函数
    @click="$store.commit('方法名',参数)"
    @click="方法名"

5,

异步修改示例(接口请求,定时器...)
import Vue from 'vue'
import Vuex from 'vuex' 
export defaul new Vuex.store({
    state:{
        count:1,
        userinfo:''
    }
    mutations:{
        add(state){
            state.count++
        }
        setInfo(state,data){
            state.userInfo:data
        }
    }
    actions:{
        getInfo(){
            $ajax({
            success:function(){
                res
            }
            })
        }
        let res=...
        commit('setInfo',res)//可以调用同步处理时的方法
    }

6,解决vuex中页面刷新后数据丢失的问题

原因 因为store中的数据是保存在内存中的,当刷新页面时,页面会重新加载vue实例,vuex中的存储在store中的数据会重新进行初始化。
解决办法及心路历程
由于vuex中的数据保存在运行内存中,因此,将其保存在缓存中就可以解决这个问题; 缓存主要有Session Storage,Local Stroage,Cookie三种,如何进行选择?
由于sessionStorage 缓存只在该页面存在时有效,所以就选择它了
应该在那个阶段,如何将VUEX中的内容存在sessionStroage中?
1,vuex中的state数据只有在mulation中能够被修改,可以在mulation中利用sessionStroage.setItem进行修改,当页面刷新时用sessionStorage.getItem获取到值,用this.store.replaceState(Object.assign(,this.store.replaceState(Object.assign({}, this.store.state,JSON.parse(sessionStorage.getItem("store"))))替代原来vuex中的state; 2,在app.vue中用beforeunload方法中将store.state存储到sessionstorage中

 created () {
    //在页面加载时读取sessionStorage里的状态信息
    if (sessionStorage.getItem("store") ) {
        this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
    } 

    //在页面刷新时将vuex里的信息保存到sessionStorage里
    window.addEventListener("beforeunload",()=>{
        sessionStorage.setItem("store",JSON.stringify(this.$store.state))
    })
  }

为什么不能直接用sessionStroage替代vuex进行存储呢? sessionStroage等用于不同页面之间的存储比较合适,当两个组件利用vuex中数据源进行通信时,一个组件中的数据源发生变化时,另一个组件中的相应数据也会响应式变化,而sessionStroage和localStroage做不到。


redux

可以用在兄弟组件之间传值,并在任意组件内引用

1,

安装步骤:

npm install -g create-react-app
create-react-app react-app
cd react-app
npm install redux react-redux npm start

2,

首先,在Index.js中利用store来存储和改变数据
import {Procider} from 'react-redux'
import store from './store'//以js结尾可以省略
ReactDOM.render(
    <Provider store={store}>
        <App/>
    </Provider>
    ,
     document.getElementById('root'));

其次,创建store.js

createStore创建一个 Redux store 来以存放应用中所有的 state,应用中应有且仅有一个 store;其中暴露 dispatch, subscribe, getState, replaceReducer 方法。
import {createStore} from 'redux'
import reducer from './reducer'
利用initState设置对象具有的属性并赋初值,存储的是状态管理的一些变量
let initState = {
  num: 0,
  userInfo: {},
}
// createStore 第一个参数是一个reducer(fun) 第二个参数是一个obj 
let store = createStore(reducer, initState)
export default store

然后,创建reducer.js
用于对store.js中的数据进行具体的操作

import { combineReducers } from "redux"

// state 需要有默认的初始值
第一个参数是设置初始值,第二个参数是action
const num = (state=0, action) => {
  switch(action.type) {
    case 'add':
      return state+1;
    case 'del':
      return state-1;
    default:
      return state
  }//对于数据进行具体的操作
 }
combineReducers() 生成一个函数,这个函数来调用你的一系列 reducer,每个reducer 根据它们的 key 来筛选出 state 中的一部分数据并处理,然后这个生成的函数再将所有reducer的结果合并成一个大的对象
const reducer = combineReducers ({
  num
})
export default reducer

然后,创建action.js
将action 暴露给store.js

action 内必须使用一个字符串类型的 type 字段来表示将要执行的动作,多数情况下,type 会被定义成字符串常量
const add = (text) => {
  return {
    type: 'add',
    text
  }
}
const del = (text) => {
  return {
    type: 'del',
    text
  }
}
export {
  add,
  del
}//导出两个方法的方式

最后,在App.js中

import {add, del} from './action'//引入同一个文件中两个方法  
import store from './store'//引入存储的文件 
--------------------------------------------------------------
在页面中调用函数的方式
    <button onClick = { () => {
      store.dispatch(add(1))//直接调用action内部的方法
    }}>add</button>  
--------------------------------------------------------------
在页面中显示store内的数据的方法
    方法一:
    {$store.getState().num}
    getState()方法能够得到state中所有的值,但是对于state的修改不会显示在页面内    
    方法二:
    import {connect} from 'react-redux'  //用来连接组件和redux,获取redux中的数据
    {this.props.num}
    const mapStateToProps = (state) => {
     return {
    num: state.num//将state内的各个属性改为props
    }
    export default connect(mapStateToProps)(App);//向函数传递了两个参数第一个参数是props属性下的num,第二个参数是组件App
}