Redux与纯JS入门实例讲解

原创 2016年11月28日 09:46:46

Redux与纯JS入门实例讲解

学习Redux可能是一个噩梦,我猜应该每个人都读过那篇”You Might Not Need Redux”然后扔掉了手中的电脑。如果一来就是npm install --save react-redux,你很可能在做了几个TodoList之类的例程之后还是不甚清楚redux究竟是做什么的,或者没那么清楚。或许,你需要的仅仅是一个不包含react的redux例子。

redux和react是什么关系

react和redux之间没有关系。

redux支持react、Angular、Ember、JQuery以及纯JS等。redux和react框架搭配起来很好用,但并不意味着学习redux的第一步就是安装React绑定库:

npm install --save react-redux

可能先看看redux对纯JS的支持更有利于理解redux。

准备工作

准备工作十分简单,你不需要安装任何依赖,不需要包管理工具,不需要模块打包工具甚至你根本就不需要模块。

打开你最喜欢的文本编辑器,将下面的HTML代码粘贴进去就可以了。

<!DOCTYPE html>
<html>
  <head>
    <title>Redux basic</title>
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>

  </body>
</html>

这里通过<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>引入了预编译好的Redux文件。

直接在浏览器打开上面的html文件然后在控制台通过全局变量window.Redux即可访问Redux对象。

可以看到其对象方法:

简单的例子

在上面的html代码中完善以下代码,一个简单的redux例子就完成了。

<!DOCTYPE html>
<html>
  <head>
    <title>Redux basic</title>
    <script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
  </head>
  <body>
    <div>
      <p><span id="colorEl">Watch my color.</span>
         <button id="red">RED</button>
         <button id="green">GREEN</button>
         <button id="toggle">TOGGLE</button>
    </div>
    <script type="text/javascript">
        var initialState = {
            color: 'red'
        }

        function color(state, action) {
            if(typeof state === 'undefined') {
                return initialState
            }

            switch(action.type) {
                case 'RED' : 
                    return { color: 'red'}
                case 'GREEN' : 
                    return { color: 'green'}
                case 'TOGGLE' :
                    return state.color === 'red' ? {color:'green'} : {color:'red'}
                default :
                    return state
            }
        }

        var store = Redux.createStore(color)
        var colorEl = document.getElementById('colorEl')

        function renderValue() {
            colorEl.style.color = store.getState().color
        }

        renderValue()
        //注册监听器
        store.subscribe(renderValue)

        document.getElementById('red').addEventListener('click', function(){
            store.dispatch({
                type: 'RED'
            })
        })

        document.getElementById('green').addEventListener('click', function(){
            store.dispatch({
                type: 'GREEN'
            })
        })

        document.getElementById('toggle').addEventListener ('click', function(){
          store.dispatch({
            type: 'TOGGLE'
          })
        })

    </script>>
  </body>
</html>

现在在浏览器打开以上html文件,试着点击里面的按钮。这就是redux在原生js中的使用。

Redux基本概念

下面结合以上简单的例子说明redux中几个基本的概念。

1、单一数据源

Redux中只有单一数据源,整个应用的所有state都被存储在一个单一的对象中。在本例中,我们只维护了一个state也就是<span id="colorEl">Watch my color.</span>的颜色属性,因此该对象中也只有一个属性:

var initalState = {
  color: 'red'
}

这是最简单的例子,当应用变得复杂的时候,我们需要首先根据应用的所有state思考设计一下这个对象的结构,但这里我们暂时不关心这个问题。

2、使用action改变应用的state

当我们需要改变应用的state的时候,不能直接修改state值,Redux中的state是只读的。

唯一改变state的方法就是触发一个action,action是一个普通的JavaScript对象,用来描述发生了什么。每个action对象都要有一个type属性,你可以理解为是唯一标识这个action的名字。

在本例中,我们给三个按钮#red,#green,#toggle分别绑定了click事件,每当点击的时候分别触发一个action,注意代码中的以下部分:

store.dispatch({
    type: 'RED'
})

store.dispatch({
    type: 'GREEN'
})

store.dispatch({
    type: 'TOGGLE'
})

store.dispatch方法中分别传入了三个对象(后面说明store.dispatch是什么)

{ type: 'RED'}

{ type: 'GREEN'}

{ type: 'TOGGLE'}

就是action,type是唯一标识他们类型的名字。action是一个用来描述发生了什么的对象,以上3个action不妨理解成发生了“变红”,“变绿”或者“切换颜色”的事情。

3、使用Reducer来执行对state的修改

action是一个普通的JavaScript对象,它用来描述发生了什么,但它并不描述发生的这个事情该怎么去修改state,如何根据action去修改state是Reducer的事情。

Reducer是什么,它就是一个纯函数,接收旧的state以及action作为输入参数,返回新的state。

在本例中就是下面这个函数:

function color(state, action) {
    if(typeof state === 'undefined') {
        return initialState
    }

    switch(action.type) {
        case 'RED' : 
            return { color: 'red'}
        case 'GREEN' : 
            return { color: 'green'}
        case 'TOGGLE' :
            return state.color === 'red' ? {color:'green'} : {color:'red'}
        default :
            return state
    }
}

Reducer决定了如何修改state,当action的type是’RED’的时候返回一个新的state其中color属性的值为’red’,当action的type是’GREEN’的时候返回一个新的state其中color属性的值为’green’,’TOGGLE’同理。

关于Reducer请注意:

  • 不要修改state的值,请返回一个新的副本;
  • 在遇到未知action时,默认情况下一定要返回旧的state;

另外请大家注意,上面的{ type: ‘RED’}对象从语义上来说是将<span id="colorEl">Watch my color!</span>变红,但要明白,这仅仅是语言的含义,至于针对这个action如何处理state那是Reducer决定的,你当然可以在触发{ type: ‘RED’}的时候将<span id="colorEl">Watch my color!</span>变绿或者甚至删掉。牢牢记住,action只是描述发生了什么,Reducer决定针对这个action做什么处理。

4、store

store是一个对象,使用Redux提供的createStore方法来生成,我们需要将Reducer作为参数传进去,在本例中:

//Reducer
function color(state, action) {
    if(typeof state === 'undefined') {
        return initialState
    }

    switch(action.type) {
        case 'RED' : 
            return { color: 'red'}
        case 'GREEN' : 
            return { color: 'green'}
        case 'TOGGLE' :
            return state.color === 'red' ? {color:'green'} : {color:'red'}
        default :
            return state
    }
}

var store = Redux.createStore(color)

store拥有以下方法:

  • 通过store.getState()方法来获取state;
  • 通过store.dispatch(action)方法来更新state;
  • 通过subscribe(listener)方法来注册监听器,state变化时自动执行该函数;

本例中:

通过store.getState()获取state,并根据state值来设置colorEl的颜色属性:

function renderValue() {
    colorEl.style.color = store.getState().color
}

通过store.subscribe()来注册监听器,每当state发生变化时执行上面的函数:

//注册监听器
store.subscribe(renderValue)

通过store.dispatch(action)来触发修改state的操作,写在事件处理程序中,点击按钮时修改state:

document.getElementById('red').addEventListener('click', function(){
    store.dispatch({
        type: 'RED'
    })
})

document.getElementById('green').addEventListener('click', function(){
    store.dispatch({
        type: 'GREEN'
    })
})

document.getElementById('toggle').addEventListener ('click', function(){
    store.dispatch({
        type: 'TOGGLE'
    })
})

总结

应用中所有的state都以一个object tree的形式存储在唯一一个store中,想要改变state的唯一方式是触发一个action,action只用来描述发生了什么,编写reducer来根据action去改变应用的state。

首先理解这一点再深入学习redux以及redux配合react的使用是不是会轻松一些?

欢迎关注我的主页

版权声明:本文为博主原创文章,未经博主允许不得转载。

Redux详解(一)

启示Redux由Flux演变而来,但受Elm的启发,避开了Flux的复杂性。 不管你有没有使用过他们,只需几分钟就能上手Redux。安装安装稳定版:npm install --save redux多...
  • geqian2010
  • geqian2010
  • 2016年05月30日 12:14
  • 6859

react+redux+redux-deferred实现ajax异步请求,真的良心之作啊!

1、在我做项目的时候,仅仅依靠redux是不能实现ajax异步请求的,网上的教程,真的坑的一逼啊!redux-thunk占主流!但是实现起来坑太多! 2、简单的东西不一定是最好的,但最好的东西一定是...
  • Take_Dream_as_Horse
  • Take_Dream_as_Horse
  • 2016年11月08日 09:45
  • 3023

最简单的React和Redux整合的例子

react redux demo
  • chenhaifeng2016
  • chenhaifeng2016
  • 2017年03月26日 14:43
  • 4292

实例讲解基于 React+Redux 的前端开发流程

前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 star 数达 42000 +,超过了 jquery 的 39000+,也即将超过前几年比较火的an...
  • fengyinchao
  • fengyinchao
  • 2016年06月02日 13:42
  • 22154

《React-Native系列》24、 结合Demo学习Redux框架

8月的最后一天了,那就打响最后一炮吧!我们介绍了Flux框架,我们打算在接下来的项目里使用Redux框架,这两天简单学习了下Redux。打算结合一个Demo来讲解。 还是先来说说概念吧。 Redux ...
  • hsbirenjie
  • hsbirenjie
  • 2016年08月31日 23:06
  • 5320

一个简单的例子让你了解React-Redux

1. (单向)数据流数据流是我们的行为与响应的抽象;使用数据流能帮我们明确了行为对应的响应,这和react的状态可预测的思想是不谋而合的。常见的数据流框架有Flux/reFlux/Redux。相比其它...
  • i10630226
  • i10630226
  • 2017年05月19日 00:55
  • 2797

实例讲解基于 React+Redux 的前端开发流程

前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 star 数达 42000 +,超过了 jquery 的 39000+,也即将超过前几年比较火的an...
  • changsimeng
  • changsimeng
  • 2017年03月22日 11:55
  • 645

实例讲解基于 React+Redux 的前端开发流程

原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s...
  • u013063153
  • u013063153
  • 2016年09月03日 17:08
  • 3461

实例讲解基于 React+Redux 的前端开发流程

前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 star 数达 42000 +,超过了 jquery 的 39000+,也即将超过前几年比较火的an...
  • u010977147
  • u010977147
  • 2016年11月30日 19:41
  • 478

Node.js基础入门实例讲解

日期:2012-9-4  来源:GBin1.com 事件驱动的编程对于初学者来说可能有点儿困难,正是这个原因使得node.js对于初学者来说不是那么容易。但是不要觉得有压力,在今天的这篇教程...
  • jjfat
  • jjfat
  • 2012年09月06日 13:25
  • 582
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Redux与纯JS入门实例讲解
举报原因:
原因补充:

(最多只允许输入30个字)