1.首先创建一个store

沙箱链接

根目录创建一个store文件夹,下面创建一个index.js

import { createStore } from '../my-redux'
// 书写reducer函数
function reducer(state = 0, action) {
    switch (action.type) {
        case "add":
            return state   1;
        case "inc":
            return state - 1;
        default:
            return state;
    }
}
// 使用createStore(reducer)创建store对象并且导出
const state = createStore(reducer);
export default state;

结合上面的代码分析

  • 创建store是redux库的createStore函数接收一个reducer函数进行创建。
import { createStore } from '../my-redux'
  • 先手写一个简单的reducer函数
// 书写reducer函数
状态值默认为0
function reducer(state = 0, action) {
    switch (action.type) {
        case "add":
            return state   1;
        case "inc":
            return state - 1;
        default:
            return state;
    }
}
  • 将创建的store导出
// 使用createStore(reducer)创建store对象并且导出
const state = createStore(reducer);
export default state;

2.其次创建一个my-redux

  • 将所有的函数都导入index.js

import createStore from './createStore'
export {
    createStore
}
  • 创建一个createStore.js
export default function createStore(reducer) {
    let currentState; // 当前state值
    let currentListeners = []; // store订阅要执行的函数储存数组
    // 获得当前state值
    function getState() {
        return currentState;
    }
    // 更新state
    function dispatch(action) {
        // 传入action 调用reducer更新state值
        currentState = reducer(currentState, action)
        // 遍历调用订阅的函数
        currentListeners.forEach((listener) => listener());
    }
    // 将订阅事件储存到currentListeners数组,并返回unsubscribe 函数来取消订阅
    function subscribe(listener) {
        currentListeners.push(listener);
        // unsubscribe 
        return () => {
            const index = currentListeners.indexOf(listener);
            currentListeners.splice(index, 1);
        };
    }
    dispatch({ type: "" }); // 自动dispatch一次,保证刚开始的currentState值等于state初始值
    // 返回store对象
    return {
        getState,
        dispatch,
        subscribe,
    }
}

可以根据上面给出的代码步步分析:

①明确createStore接收一个reducer函数作为参数。

②createStore函数返回的是一个store对象,store对象包含getState,dispatch,subscribe等方法。

  • 逐步书写store上的方法

书写getState()方法

返回值:当前状态值

// 获得当前state值
    function getState() {
        return currentState;
    }

书写dispatch方法

接受参数:action。

dispatch方法,做的事情就是:①调用reducer函数更新state。②调用store订阅的事件函数。

currentState是当前状态值,currentListeners是储存订阅事件函数的数组。

    // 更新state
    function dispatch(action) {
        // 传入action 调用reducer更新state值
        currentState = reducer(currentState, action)
        // 遍历调用订阅的函数
        currentListeners.forEach((listener) => listener());
    }

书写subscribe方法

接受参数:一个函数 返回值:一个函数,用于取消订阅unsubscribe

    // 将订阅事件储存到currentListeners数组,并返回unsubscribe 函数来取消订阅
    function subscribe(listener) {
        currentListeners.push(listener);
        // unsubscribe 
        return () => {
            const index = currentListeners.indexOf(listener);
            currentListeners.splice(index, 1); // 删除函数
        };
    }

返回store对象

    // 返回store对象
    return {
        getState,
        dispatch,
        subscribe,
    }

特别注意:

初始进入createStore函数的时候,需要通过dipatch方法传入一个独一无二的action(reducer函数默认返回state)来获取初始的store赋值给currentStore。

可以结合下面reducer的default项和createStore方法调用的dispatch来理解

 dispatch({ type: "" }); // 自动dispatch一次,保证刚开始的currentState值等于state初始值
// 书写reducer函数
function reducer(state = 0, action) {
    switch (action.type) {
        case "add":
            return state   1;
        case "inc":
            return state - 1;
        default:
            return state;
    }
}

这样我们的createStore函数就已经完成了。那接下来就是检查我们写的这玩意是否起作用没有了。

3.创建一个Test组件进行检测。

老规矩先抛全部代码

import React, { Component } from 'react'
import store from './store' // 引入store对象
export default class Test extends Component {
    // 组件挂载之后订阅forceUpdate函数,进行强制更新
    componentDidMount() {
        this.unsubscribe = store.subscribe(() => {
            this.forceUpdate()
        })
    }
    // 组件卸载后取消订阅
    componentWillUnmount() {
        this.unsubscribe()
    }
    // handleclick事件函数
    add = () => {
        store.dispatch({ type: 'add' });
        console.log(store.getState());
    }
    inc = () => {
        store.dispatch({ type: 'inc' });
        console.log(store.getState());
    }
    render() {
        return (
            <div>
                {/* 获取store状态值 */}
                <div>{store.getState()}</div>
                <button onClick={this.add}> </button>
                <button onClick={this.inc}>-</button>
            </div>
        )
    }
}

1. 将Test组件记得引入App根组件

import Test from './Test';
function App() {
  return (
    <div className="App">
      <Test />
    </div>
  );
}
export default App;

2. 将store引入Test组件

import React, { Component } from 'react'
import store from './store' // 引入store对象

3. 创建一个类组件,并且使用store.getState()获得状态值

<div>
    {/* 获取store状态值 */}
    <div>{store.getState()}</div>
    <button onClick={this.add}> </button>
    <button onClick={this.inc}>-</button>
</div>

4. 书写对应的点击按钮

    // handleclick事件函数
    add = () => {
        store.dispatch({ type: 'add' });
        console.log(store.getState());
    }
    inc = () => {
        store.dispatch({ type: 'inc' });
        console.log(store.getState());
    }
    <div>
        {/* 获取store状态值 */}
        <div>{store.getState()}</div>
        <button onClick={this.add}> </button>
        <button onClick={this.inc}>-</button>
    </div>

这样是不是就可以实现了呢?哈哈哈,傻瓜,你是不是猛点鼠标,数字还是0呢?

当然,这里我们只是更新了store,但是并没有更新组件,状态的改变可以导致组件更新,但是store又不是Test组件的状态。

这里我们使用一个生命周期函数componentDidMount和store的订阅函数进行更新组件的目的,使用componentWillUnmount和store的取消订阅函数(订阅函数的返回值)。

    // 组件挂载之后订阅forceUpdate函数,进行强制更新
    componentDidMount() {
        this.unsubscribe = store.subscribe(() => {
            this.forceUpdate()
        })
    }
    // 组件卸载后取消订阅
    componentWillUnmount() {
        this.unsubscribe()
    }

好了。这里我们就真实实现了一个简单的createStore函数来创建store。

以上就是简易的redux createStore手写实现示例的详细内容,更多关于手写redux createStore的资料请关注Devmax其它相关文章!

简易的redux createStore手写实现示例的更多相关文章

  1. ios – 使用react-native-router-flux和redux,如何更新视图组件中的状态?

    为了完整起见,整个代码可以在github找到.解决方法您可能忘记将Launch组件连接到商店.你想要做的是类似于你在ExampleContainer中所做的,即然后正确的值将显示在您的日志中

  2. 万字详解JavaScript手写一个Promise

    这篇文章主要介绍了万字详解JavaScript手写一个Promise,Promise就是一个类,在执行这个类的时候,需要传递一个执行器(回调函数)进去,执行器会立即执行

  3. 分享10个常见的JavaScript前端手写功能

    这篇文章主要分享10个常见的前端手写功能,防抖、节流、深拷贝、异步控制并发数、继承等功能技巧,具有一定的参考价值,需要的小伙伴可以参考一下

  4. PyTorch实现手写数字的识别入门小白教程

    这篇文章主要介绍了python实现手写数字识别,非常适合小白入门学习,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解React 和 Redux的关系

    这篇文章主要为大家介绍了React 和 Redux的关系,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  6. redux功能强大的Middleware中间件使用学习

    这篇文章主要为大家介绍了redux功能强大的Middleware中间件使用学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  7. Redux模块化拆分reducer函数流程介绍

    Reducer是个纯函数,即只要传入相同的参数,每次都应返回相同的结果。不要把和处理数据无关的代码放在Reducer里,让Reducer保持纯净,只是单纯地执行计算,这篇文章主要介绍了Redux拆分reducer函数流程

  8. React路由中的redux和redux知识点拓展

    这篇文章主要介绍了React路由中的redux和redux知识点拓展,文章围绕主题展开详细的内容介绍,具有一定的参考价值,感兴趣的朋友可以参考学习一下

  9. 一文教会你用redux实现computed计算属性

    在computed中,可以定义一些属性,即计算属性,下面这篇文章主要给大家介绍了关于如何利用redux实现computed计算属性的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

  10. React immer与Redux Toolkit使用教程详解

    这篇文章主要介绍了React中immer与Redux Toolkit的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部