不写个简单的redux,你怕不知道我是个前端

redux使用数据流程以下:
javascript

由上可知,咱们须要一个函数来保存状态值,并暴露出修改,获取,同步的方法,下面开始进行推理html

准备工做

没有react-create-app安装后再建立reduxLearnjava

npm install -g create-react-app
复制代码

react-create-app reduxLearn复制代码

开始操刀制做新鲜的redux

关于createStore

删除publicsrc下全部的文件,建立reduxLearn/public/index.htmlreact


新建reduxLearn/src/index.jsgit

设置一个变量来保存咱们想要的效果github

let state = {
    title: {
        color: 'red',
        text: '标题'
    },
    content: {
        color: 'pink',
        text: '内容'
    }
}
复制代码

建立渲染方法npm

function renderApp(appState) {
    renderTitle(appState.title)
    renderContent(appState.content)
}
function renderTitle(title) {
    let titleEle = document.getElementById('title')
    titleEle.innerHTML = title.text
    titleEle.style.color = title.color
}
function renderContent(content) {
    let contentEle = document.getElementById('content')
    contentEle.innerHTML = content.text
    contentEle.style.color = content.color
}
function render() {
    renderApp(state)
}复制代码

若是在执行 renderApp(initState)以前的某个地方执行了initState=nullredux

页面就会报错 TypeError: Cannot read property 'title' of null数组

为了是initState不被胡乱修改,咱们须要搞个函数把它保护起来createStore

function createStore() {
    let state = {
        title: {
            color: 'red',
            text: '标题'
        },
        content: {
            color: 'pink',
            text: '内容'
        }
    }
}复制代码

变量被保护起来了,须要用的时候怎么获取呢?bash

须要提供getState暴露出变量的结果

function createStore() {
    let state = {
        title: {
            color: 'red',
            text: '标题'
        },
        content: {
            color: 'pink',
            text: '内容'
        }
    }
     //获取状态
     function getState() {
        return state
    }
    return {
      getState
    }
}

//使用状态
let store = createStore(reducer)
...
function render() {
    renderApp(store.getState())
}

复制代码

若是咱们想改变这个状态的值怎么办呢?

提供dispatch,可是你要须要告诉我改变什么,怎么改变即action

  • 定义类型

const TITLE_COLOR = 'TITLE_COLOR'
const TITLE_TEXT = 'TITLE_TEXT'
const CONTENT_COLOR = 'CONTENT_COLOR'
const CONTENT_TEXT = 'CONTENT_TEXT'复制代码

  • 建立dispatch方法,暴露出来
//派发
    function dispatch(action) {
        switch (action.type) {
            case TITLE_COLOR:
                state.title.color = action.color
                break;
            case TITLE_TEXT:
                state.title.text = action.text
                break;
            case CONTENT_COLOR:
                state.content.color = action.color
                break;
            case CONTENT_TEXT:
                state.content.text = action.text
                break;
            default:
                return state
        }
    }
复制代码
  • 调用dispatch

store.dispatch({ type: TITLE_COLOR, color: 'blue' })
store.dispatch({ type: TITLE_TEXT, text: '修改标题了' })
render()
复制代码
  • 看效果


在实际开发中初始状态state和操做步骤dispatch不是固定的咱们须要提取出来

function createStore(reducer) {
    let state;
    //派发
    function dispatch(action) {
        state = reducer(state, action)//经过reducer处理返回结果值
    }
    //获取状态
    function getState() {
        return state
    }
    //执行一次,目的是设置默认值
    dispatch({ type: "@@TYPE_INIT_STATE" })
    return {
        dispatch,
        getState,
    }
}
复制代码
  • 如今开始写reducer 函数,须要状态值和操做类型两个参数

//声明初始值
const initState = {
    title: {
        color: 'red',
        text: '标题'
    },
    content: {
        color: 'pink',
        text: '内容'
    }
}
//reducer 这里返回的数据应是新对象->state = reducer(state, action)//经过reducer处理返回结果值
function reducer(state = initState, action) {
    switch (action.type) {
        case TITLE_COLOR:
            return { ...state, title: { ...state.title, color: action.color } }
        case TITLE_TEXT:
            state.title.text = action.text
            return { ...state, title: { ...state.title, text: action.text } }
        case CONTENT_COLOR:
            state.content.color = action.color
            return { ...state, content: { ...state.content, color: action.color } }
        case CONTENT_TEXT:
            return { ...state, content: { ...state.content, text: action.text } }
        default:
            return state
    }
}复制代码
  • 修改引用

let store = createStore(reducer)复制代码

发现每次修改都要从新调用render()才生效,很麻烦,若是咱们在每次修改时添加监听事件,触发订阅模式,则能够一劳永逸

添加订阅函数

  • 订阅函数

function createStore(reducer) {
    let state;
    //订阅添加监听函数数组
    let listeners = []
    //派发
    function dispatch(action) {
        state = reducer(state, action)
        //订阅
        listeners.forEach(l => l())
    }
    //订阅,返回一个取消订阅的方法
    function subscribe(listener) {
        listeners.push(listener)
        return function () {
            listeners = listeners.filter(item => item != listener)
        }

    }
    //获取状态
    function getState() {
        return state
    }
    dispatch({ type: "@@TYPE_INIT_STATE" })
    return {
        dispatch,
        getState,
        subscribe
    }
}

复制代码
  • 调用时订阅函数

store.subscribe(render)复制代码

  • 测试订阅函数和取消订阅函数

store.subscribe(render)

setTimeout(() => {
    store.dispatch({ type: TITLE_COLOR, color: 'blue' })
    store.subscribe(render)()//取消订阅
    store.dispatch({ type: TITLE_TEXT, text: '修改标题了' })
}, 1000);
复制代码
  • 效果以下


提取createStore函数

  • 新建reduxLearn/src/redux/createStore.js

export default function createStore(reducer) {
    let state;
    let listeners = []
    //派发
    function dispatch(action) {
        state = reducer(state, action)
        //订阅
        listeners.forEach(l => l())
    }
    //订阅,返回一个取消订阅的方法
    function subscribe(listener) {
        listeners.push(listener)
        return function () {
            listeners = listeners.filter(item => item != listener)
        }

    }
    //获取状态
    function getState() {
        return state
    }
    dispatch({ type: "@@TYPE_INIT_STATE" })
    return {
        dispatch,
        getState,
        subscribe
    }
}

复制代码


  • 新建reduxLearn/src/redux/index.js

import createStore from './createStore'
export {
    createStore,
}复制代码


  • 在使用时直接调用就能够使用了

import { createStore } from './redux'复制代码

createStore总结

要想保护数据要找个函数包裹起来createStore,可变的因素reducer能够经过参数传递进来,对数据的操做能够在函数内部暴露给外面getstate,dispatch,subscribe

在使用时直接把使用函数赋值给变量store,使用变量.函数store.getState()便可


项目地址:

https://github.com/XinYueXiao/interviewHighlights/tree/master/reduxLearn

相关文章
相关标签/搜索