zoukankan      html  css  js  c++  java
  • Redux架构模式

    1.抽离 store 和监控数据变化

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Redux架构模式</title>
        <style type="text/css">
        </style>
    </head>
    
    <body>
        <div id='title'></div>
        <div id='content'></div>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <script type="text/javascript">
        $(function() {
            function createStore(state, stateChanger) {
                const listeners = []
                const subscribe = (listener) => listeners.push(listener)
                const getState = () => state
                const dispatch = (action) => {
                    stateChanger(state, action)
                    listeners.forEach((listener) => listener())
                }
                return { getState, dispatch, subscribe }
            }
    
            function renderApp(appState) {
                renderTitle(appState.title)
                renderContent(appState.content)
            }
    
            function renderTitle(title) {
                const titleDOM = document.getElementById('title')
                titleDOM.innerHTML = title.text
                titleDOM.style.color = title.color
            }
    
            function renderContent(content) {
                const contentDOM = document.getElementById('content')
                contentDOM.innerHTML = content.text
                contentDOM.style.color = content.color
            }
    
            let appState = {
                title: {
                    text: 'React.js 小书',
                    color: 'red',
                },
                content: {
                    text: 'React.js 小书内容',
                    color: 'blue'
                }
            }
    
            function stateChanger(state, action) {
                switch (action.type) {
                    case 'UPDATE_TITLE_TEXT':
                        state.title.text = action.text
                        break
                    case 'UPDATE_TITLE_COLOR':
                        state.title.color = action.color
                        break
                    default:
                        break
                }
            }
    
            const store = createStore(appState, stateChanger)
            store.subscribe(() => renderApp(store.getState())) // 监听数据变化
    
            renderApp(store.getState()) // 首次渲染页面
            store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: '《React.js 小书》' }) // 修改标题文本
            store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色    
        })
        </script>
    </body>
    
    </html>

    2.共享结构的对象提高性能

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Redux架构模式</title>
        <style type="text/css">
        </style>
    </head>
    
    <body>
        <div id='title'></div>
        <div id='content'></div>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <script type="text/javascript">
        $(function() {
            function createStore(state, stateChanger) {
                const listeners = []
                const subscribe = (listener) => listeners.push(listener)
                const getState = () => state
                const dispatch = (action) => {
                    state = stateChanger(state, action) // 覆盖原对象
                    listeners.forEach((listener) => listener())
                }
                return { getState, dispatch, subscribe }
            }
    
            function renderApp(newAppState, oldAppState = {}) { // 防止 oldAppState 没有传入,所以加了默认参数 oldAppState = {}
                if (newAppState === oldAppState) return // 数据没有变化就不渲染了
                console.log('render app...')
                renderTitle(newAppState.title, oldAppState.title)
                renderContent(newAppState.content, oldAppState.content)
            }
    
            function renderTitle(newTitle, oldTitle = {}) {
                if (newTitle === oldTitle) return // 数据没有变化就不渲染了
                console.log('render title...')
                const titleDOM = document.getElementById('title')
                titleDOM.innerHTML = newTitle.text
                titleDOM.style.color = newTitle.color
            }
    
            function renderContent(newContent, oldContent = {}) {
                if (newContent === oldContent) return // 数据没有变化就不渲染了
                console.log('render content...')
                const contentDOM = document.getElementById('content')
                contentDOM.innerHTML = newContent.text
                contentDOM.style.color = newContent.color
            }
    
            let appState = {
                title: {
                    text: 'React.js 小书',
                    color: 'red',
                },
                content: {
                    text: 'React.js 小书内容',
                    color: 'blue'
                }
            }
    
            function stateChanger(state, action) {
                switch (action.type) {
                    case 'UPDATE_TITLE_TEXT':
                        return { // 构建新的对象并且返回
                            ...state,
                            title: {
                                ...state.title,
                                text: action.text
                            }
                        }
                    case 'UPDATE_TITLE_COLOR':
                        return { // 构建新的对象并且返回
                            ...state,
                            title: {
                                ...state.title,
                                color: action.color
                            }
                        }
                    default:
                        return state // 没有修改,返回原来的对象
                }
            }
    
            const store = createStore(appState, stateChanger)
            let oldState = store.getState() // 缓存旧的 state
            store.subscribe(() => {
                const newState = store.getState() // 数据可能变化,获取新的 state
                renderApp(newState, oldState) // 把新旧的 state 传进去渲染
                oldState = newState // 渲染完以后,新的 newState 变成了旧的 oldState,等待下一次数据变化重新渲染
            })
    
            renderApp(store.getState()) // 首次渲染页面
            store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: '《React.js 小书》' }) // 修改标题文本
            store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色       
        })
        </script>
    </body>
    
    </html>

    3.reducer

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <title>Redux架构模式</title>
        <style type="text/css">
        </style>
    </head>
    
    <body>
        <div id='title'></div>
        <div id='content'></div>
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <script type="text/javascript">
        $(function() {
            function createStore(reducer) {
                let state = null
                const listeners = []
                const subscribe = (listener) => listeners.push(listener)
                const getState = () => state
                const dispatch = (action) => {
                    state = reducer(state, action) // 覆盖原对象
                    listeners.forEach((listener) => listener())
                }
                dispatch({}) // 初始化 state
                return { getState, dispatch, subscribe }
            }
    
            function renderApp(newAppState, oldAppState = {}) { // 防止 oldAppState 没有传入,所以加了默认参数 oldAppState = {}
                if (newAppState === oldAppState) return // 数据没有变化就不渲染了
                console.log('render app...')
                renderTitle(newAppState.title, oldAppState.title)
                renderContent(newAppState.content, oldAppState.content)
            }
    
            function renderTitle(newTitle, oldTitle = {}) {
                if (newTitle === oldTitle) return // 数据没有变化就不渲染了
                console.log('render title...')
                const titleDOM = document.getElementById('title')
                titleDOM.innerHTML = newTitle.text
                titleDOM.style.color = newTitle.color
            }
    
            function renderContent(newContent, oldContent = {}) {
                if (newContent === oldContent) return // 数据没有变化就不渲染了
                console.log('render content...')
                const contentDOM = document.getElementById('content')
                contentDOM.innerHTML = newContent.text
                contentDOM.style.color = newContent.color
            }
    
            function reducer (state, action) {
              if (!state) {
                return {
                  title: {
                    text: 'React.js 小书',
                    color: 'red',
                  },
                  content: {
                    text: 'React.js 小书内容',
                    color: 'blue'
                  }
                }
              }
              switch (action.type) {
                case 'UPDATE_TITLE_TEXT':
                  return {
                    ...state,
                    title: {
                      ...state.title,
                      text: action.text
                    }
                  }
                case 'UPDATE_TITLE_COLOR':
                  return {
                    ...state,
                    title: {
                      ...state.title,
                      color: action.color
                    }
                  }
                default:
                  return state
              }
            }
    
            const store = createStore(reducer)
            let oldState = store.getState() // 缓存旧的 state
            store.subscribe(() => {
                const newState = store.getState() // 数据可能变化,获取新的 state
                renderApp(newState, oldState) // 把新旧的 state 传进去渲染
                oldState = newState // 渲染完以后,新的 newState 变成了旧的 oldState,等待下一次数据变化重新渲染
            })
    
            renderApp(store.getState()) // 首次渲染页面
            store.dispatch({ type: 'UPDATE_TITLE_TEXT', text: '《React.js 小书》' }) // 修改标题文本
            store.dispatch({ type: 'UPDATE_TITLE_COLOR', color: 'blue' }) // 修改标题颜色       
        })
        </script>
    </body>
    
    </html>

    不知不觉地,到这里大家不仅仅已经掌握了 Redux,而且还自己动手写了一个 Redux。我们从一个非常原始的代码开始,不停地在发现问题、解决问题、优化代码的过程中进行推演,最后把 Redux 模式自己总结出来了。这就是所谓的 Redux 模式,我们再来回顾一下这几节我们到底干了什么事情。

    我们从一个简单的例子的代码中发现了共享的状态如果可以被任意修改的话,那么程序的行为将非常不可预料,所以我们提高了修改数据的门槛:你必须通过 dispatch 执行某些允许的修改操作,而且必须大张旗鼓的在 action 里面声明。

    这种模式挺好用的,我们就把它抽象出来一个 createStore,它可以产生 store,里面包含 getStatedispatch 函数,方便我们使用。

    后来发现每次修改数据都需要手动重新渲染非常麻烦,我们希望自动重新渲染视图。所以后来加入了订阅者模式,可以通过 store.subscribe 订阅数据修改事件,每次数据更新的时候自动重新渲染视图。

    接下来我们发现了原来的“重新渲染视图”有比较严重的性能问题,我们引入了“共享结构的对象”来帮我们解决问题,这样就可以在每个渲染函数的开头进行简单的判断避免没有被修改过的数据重新渲染。

    我们优化了 stateChanger 为 reducer,定义了 reducer 只能是纯函数,功能就是负责初始 state,和根据 stateaction 计算具有共享结构的新的 state

    createStore 现在可以直接拿来用了,套路就是:

    // 定一个 reducer
    function reducer (state, action) {
      /* 初始化 state 和 switch case */
    }
    
    // 生成 store
    const store = createStore(reducer)
    
    // 监听数据变化重新渲染页面
    store.subscribe(() => renderApp(store.getState()))
    
    // 首次渲染页面
    renderApp(store.getState()) 
    
    // 后面可以随意 dispatch 了,页面自动更新
    store.dispatch(...)
  • 相关阅读:
    LVS/NAT 配置
    LVS 介绍
    Nagios 服务安装
    Mysql 主从复制搭建
    GitHub托管BootStrap资源汇总
    基于bootstrap的datatable控件
    微信在线客服系统-微信公众平台开发
    UI Prototype Design IDE( 界面原型设计工具 )
    vlc多功能播放器
    javaC#php主流语言实现FMS流媒体传输协议RTMP的开源组件
  • 原文地址:https://www.cnblogs.com/xutongbao/p/9924774.html
Copyright © 2011-2022 走看看