美文网首页
待定:如何上手Redux + 源码运行问题填坑

待定:如何上手Redux + 源码运行问题填坑

作者: 赛博剑仙_李玄器 | 来源:发表于2019-12-27 18:35 被阅读0次

    我是如何快速上手的?

    第一步:快速通览一遍官方技术文档介绍基础部分,在脑海中大致对Redux有一个基础印象。没看懂的先跳过,不用做笔记!不用做笔记!不用做笔记!(学习要掌握方式方法,这阶段是让你建立印象的过程,别把自己绊住)
    第二步:直接看官方redux项目里Counter计数器的代码实例(这是最简单的例子)

    在Terminal或命令行依次执行下列指令:
    1. 获取redux源码
    git clone https://github.com/reactjs/redux.git
    
    2. 进入到examples/counter实例的路径下
    cd redux/examples/counter
    
    3. 安装项目依赖
    npm install
    
    4. 运行项目
    npm start  //运行项目的过程中报错,解决方法放在文章末尾
    

    第三步:代码看的有点晕,有些地方模棱两可,所以产生问题要立刻去查,把查到的问题写在笔记上。
    第四步:看阮一峰老师的Redux入门教程(一)从设计思想开始,一直看到最后,太前面的不用看,首部是劝你不要迷信使用Redux的,与学习此项技能无关。
    第五步:有些找到感觉了,对照着入门教程看代码,隐约能感受到代码逻辑执行的步骤。理清思路,尝试完整复述一遍。

    至此,Redux基本入门,可以继续深入学习了。下面是我关于自己学习过程中的一些问题整理。


    问题合集!

    问题一:为什么Redux的counter示例在npm start后可以在Network上运行,不能在Local运行?
    (未解决,由于我用的是VM的Linux虚拟机,初步怀疑是接口问题,打算换个电脑试下)
    问题二:为什么每个组件的 js 文件头部都要引入 import React from 'react' ?
    答:因为每一个文件都是一个单独的模块,不引入的话就不能识别文件中的React是什么。
    我们在代码中看到的结构可能是这样的,认为没用到React

    import React, { Component } from 'react';
    
    class Process extends Component {
      render() {
        return (<div>哈哈哈</div>)
      } 
    }
    

    但上述代码经过babel转译过后是这样的,其实是用到了React.createElement这个组件方法,所以如果不引用模块,则不能识别文件中的React是什么。

    import React, { Component } from 'react';
    
    class Process extends Component {
      render() {
        return React.createElement(
          'div',
          null,
          '\u54C8\u54C8\u54C8'
        );
      }
    }
    

    如果觉得每个文件都引用一遍太麻烦,你可以在webpack中将React配置为全局变量。

    plugins:[
        //自动加载模块,而不必到处 import 或 require 。
        new webpack.ProvidePlugin({
          React: "React"
        })
      ]
    
    

    关于import导入组件的理解:

    import a from 'module-name'     //导入module-name模块(组件)中的默认组件,命名为a
    import * as a from 'module-name'      //导入module-name模块(组件)中的所有组件,并命名为a
    import {a} from 'module-name'   //导入module-name模块(组件)中的单个成员a组件
    import {a as b} from 'module-name'      //导入module-name模块(组件)中的成员组件a,并重命名为b
    
    //如果a组件中包含一个doAllTheAmazingThings()接口(export),可以这样调用
    a.doAllTheAmazingThings();
    

    问题三:为什么React里总是要bind绑定

    在JavaScript中,以下两种写法是不等价的:

    let obj = {
        tmp:'Yes!',
        testLog:function(){
            console.log(this.tmp);
        }
    };
    
    obj.testLog();      //此时为obj调用testLog函数,其中的this指向obj,所以结果为Yes
    
    let tmpLog = obj.testLog;
    tmpLog();       //此时为window调用tmpLog函数,其中this指向window,但window没有定义tmp,所以结果为undefined
    

    bind 方法确保了第二种写法与第一种写法相同。看了好多博客都说是this丢失了指向,可以这么理解。
    究其原因,我觉得只是因为在不同作用域里调用了同一个函数。而函数里面的this,由于指向不同外部环境从而产生了问题,this指向没丢,指的方向不同罢了。

    所以为了防止出现这个问题,我们就在构造函数里利用bind()特性:创建一个新函数,并且该函数拥有指定this的值。再把新函数初始化赋值给我们接下来要用到的同名方法。

    简单理解,就是告诉程序,render里如果出现一个this.function,先去看构造函数初始化里,我有没有提前声明它的this指向,如果有,就别指向window。

    import React, { Component } from 'react'
    
    class Counter extends Component {
      constructor(props) {
        super(props);
        this.incrementAsync = this.incrementAsync.bind(this);   //bind()返回拥有指定this的原函数的拷贝,然后初始化赋值给左端
      }
    
      incrementAsync() {
        setTimeout(this.props.onIncrement, 1000)
      }
    
      render() {
        return (
          <p>
            <button onClick={this.incrementAsync}>
              Increment async
            </button>
          </p>
        )
      }
    }
    
    

    问题四:store.dispatch(action)执行后都发生了哪些事情?
    它会触发Reducer的自动执行,所以需要在创建Store的时候,传入Reducer

    import { createStore } from 'redux';
    const store = createStore(reducer);
    
    store.subscribe(listener);
    

    全部逻辑:store.dispatch(action)会把接收的Action传给Reducer,然后触发Reducer的自动调用,得到新的State,State 发生变化,就自动触发执行store.subscribe方法。

    显然,只要把 View 的更新函数(对于 React 项目,就是组件的render方法或setState方法)放入listen,就会实现 View 的自动渲染。

    PS: store.subscribe方法返回一个函数,调用这个函数就可以解除监听。

    let unsubscribe = store.subscribe(() =>
      console.log(store.getState()));
      
      unsubscribe();
    

    PS:counter运行npm start报错问题解决
    首先,执行npm install命令安装了项目依赖之后,再执行npm start运行项目。本来很正常的操作,但是却突然报错。 报错部分截图
    上面的错误信息没有太多价值,就是告诉了我们,counter这个脚本文件运行失败,关键的内容在倒数第三行,npm ERR!,后面紧接着又说,这可能不是npm的错,上面还有些信息,去看看吧。 上面的错误日志
    结果向上滑就看到了这一大坨提示,开发者自己都知道这段话很长,但确实很有用。我本来是拒绝的,但没办法,百度没搜到解决方案(别喷我没有谷歌,下次一定。主要是Google的解决方案也大都是英文的,没这阅读习惯,不过从今天开始就要改变了)

    回过头来,静下心看这些日志提示,会发现逻辑其实写的很清楚。

    首先,它告诉我们这个内容的项目依赖树有问题,不赖React,我们需要调整本地一些内容。

    接着,指出了项目依赖问题出在babel-eslint这个包上,因为我们现在的版本是10.0.3,但是这个项目只能跑10.0.1的版本上。而且不让我们自己手动安装这一个版本,说手动安装出了兼容性问题不好调试。

    那怎么办呢?下一行红字给我们提出了一个眼不见心不烦的方法:忽略报错,当然问题还是会在。这我一直没理解他们啥意思,搞笑吗?

    再向下就到了问题的解决方法这里,如下是问题解决方法:

    1. 在项目文件夹里,删除package-lock.json(不是package.json!)和/或yarn.lock。
    2. 删除node_modules文件。
    3. 从项目文件夹的package.json文件的,dependencies 和/或 devDependencies中删除“babel eslint”。
    4. 运行npm install或yarn重现安装依赖,用哪种方法具体取决于你用的包管理器。

    注意,在redux文件下进行上述操作,counter里不需要改动package,只是进入counter路径下运行一次npm install即可。
    接下来,terminal又重复提示了两次类似的错误,不过第3项变成了删除babel-jest和eslint


    总共需删除的内容

    重复上述操作,在redux文件下,删除package-lock.json,删除node_modules,package.json文件下删除对应的包,重新执行npm install。然后在counter路径下运行npm install执行项目脚本。

    运行结果如图

    最后附我理解的Counter逻辑流程图,欢迎各位在评论区交流看法,分享你总结的问题,祝你早日成为代码王。


    Counter的Redux逻辑

    相关文章

      网友评论

          本文标题:待定:如何上手Redux + 源码运行问题填坑

          本文链接:https://www.haomeiwen.com/subject/srgdoctx.html