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

我是如何快速上手的?

第一步:快速通览一遍官方技术文档的介绍基础部分,在脑海中大致对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 (
哈哈哈
) } }

但上述代码经过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 (
      

) } }

问题四: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运行项目。本来很正常的操作,但是却突然报错。
待定:如何上手Redux + 源码运行问题填坑_第1张图片
报错部分截图

上面的错误信息没有太多价值,就是告诉了我们,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 + 源码运行问题填坑_第2张图片
总共需删除的内容

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

待定:如何上手Redux + 源码运行问题填坑_第3张图片
运行结果如图


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


待定:如何上手Redux + 源码运行问题填坑_第4张图片
Counter的Redux逻辑

你可能感兴趣的:(待定:如何上手Redux + 源码运行问题填坑)