每日学习

2019.3.38

比较两个文件

英文

  1. detect: 检测
    2019.3.27

如何找到第一个bug出现的commit??

  1. 设置commit的起点和终点
    git bisect start [终点] [起点]
  2. 查看页面是否有bug
    • 如果有
      git bisect bad
    • 如果没有
      git bisect good
  3. 重复第二步
  4. 找到第一次提交bug的commit hash 了
  5. 切换到这个commit, 在一个新分支
    git checkout -b <分支名称>

完成一次工单流程

  1. 查看相应的issue

  2. 在本地最新的master创建一个分支, 分支名如下


    image.png
  3. 在第二步新建的分支开发

  4. 创建远程分支


    image.png
  5. git branch确保在第二步的分支中

  6. git push origin <第二步的分支名称>

  7. 申请mr


    image.png
  8. 填写mr信息


    image.png

    注意:

    1. bug的话要按照以下格式写在description中
    2. assignee给机器人
问题现象:选择 edu sp 模式, 使用基础动作的举左手, 举右手模块, 机器人的预期动作与实际动作相反

问题原因:`Blocks/action_blocks_sp.js`文件举左手, 举右手模块定义动作代码错误

解决方法:根据`Blocks/action_blocksaelos.js`文件, 修改相应代码

第一次引入这个 bug 的 commit : [79c04904](/aelos_blockly_edu/aelos_blockly_edu/commit/79c04904abc7f57b5a0a84d86653e1a194b15c15 "Feat: 添加串口教育版动作文件以及相关资源,并添加对刚度命令的处理")

该 commit 的author: xxxx

  1. 等待mr

英语

  1. 翻译1
    When webpack processes your application, it internally builds a dependency graph which maps every module your project needs and generates one or more bundles.
    当 webpack 处理你的应用, 它在内部建立一个依赖图, 它知道你的项目所需要的每一个模块, 生成一个或者多个包.
    生词: process: v处理 / internally 内部的 / map: 映射
  2. 翻译2
    Since version 4.0.0, webpack does not require a configuration file to bundle your project, nevertheless it is incredibly configurable to better fit your needs.
    从 4.0.0 开始, webpack不再需要配置文件去打包你的项目, 尽管如此, 它还是可配置的为了符合你的需求.
    尽管如此, 它还是高度可配置性, 可以很好满足你的需求
    生词: nevertheless: 尽管如此/ incredible configurable: 高度(非常)可配置/
  3. 翻译3
    This document is intended to give a high-level overview of these concepts, while providing links to detailed concept-specific use cases.
    这个文档想要简略的介绍这些概念, 同时也提供超链接, 用来详细??
    同时提供具体概念的详尽相关用例
    生词: intended: 想要
  4. 翻译4
    For a better understanding of the ideas behind module bundlers and how they work under the hood, consult these resources:
    为了更好的理解模块打包的想法,
    生词: bundle: 包裹/bundler: 打包工具/under the hood: 在底层/consult: 咨询, 参考
  5. 翻译5
    An entry point indicates / which module / webpack should use to / begin building out its internal dependency graph. webpack will figure out / which other modules and libraries / that entry point depends on (directly and indirectly).
    一个入口文件指示哪些模块打包
    一个入口起点指示 webpack 应该使用哪一个模块构建它的内部依赖图. webpack 将会算出入口起点依赖(直接和间接)哪些模块(文件)和库
    生词: indicates: 指示/ build out: 构建 / module: 模块, 可以认为文件 /
  6. 翻译6
    The output property tells webpack / where to emit the bundles it creates / and / how to name these files. It defaults to ./dist/main.js for the main output file and to the ./dist folder for any other generated file.
    输出属性告诉 webpack 生成的包放在哪里, 并且如何命名这些文件. 默认是将主要输出文件放到./dist/main.js, 其他生成的文件放到./dist目录下.
    生词: emit: 输出 /
  7. 翻译7
    You can configure this part of the process by specifying an output field in your configuration:
    你可以配置这段过程, 通过指定一个输出字段, 在你的配置中.
    生词: part of the process: 处理过程 / field: 字段
  8. 翻译8
    In the example above, we use the output.filename and the output.path properties to tell webpack the name of our bundle and where we want it to be emitted to. In case you're wondering about the path module being imported at the top, it is a core Node.js module that gets used to manipulate file paths.
  9. 翻译9
    Module not found: You attempted to import ../../node_modules/react-data-grid-modify which falls outside of the project src/ directory. Relative imports outside of src/ are not supported. You can either move it inside src/, or add a symlink to it from project's node_modules/.
    模块未找到: 你尝试引入../../node_modules/react-data-grid-modify,这个模块路径跑到了这个项目的src/路径之外. 从外部的src/相对引入是不支持的.你可以把它移动到src/内, 或者从项目的node_modules/添加一个 symlink
    2019.3.24

git

一般流程

  1. git checkout master
  2. 拉取 origin/master到本地master
    git pull -p --all
  3. 根据本地master创建开发分支
    git checkout -b raojiajun/#fix1
  4. git add /git commit
  5. 工作速度
    • 当天push
      1. git push origin raojiajun/#fix1
    • 不能当天push(origin/master发生变化git, 终端提示你需要pull )
      1. git checkout master
      2. 拉取最新的origin/master 到本地master
        git pull -p --all
      3. git checkout raojiajun/#fix1
      4. 本地master改动体现到开发分支
        git merge master
        • 如果修改同一个文件, 需要手动解决冲突
        • 如果没有修改同一个文件, 正常开发
      5. git add /git commit
      6. git push origin raojiajun/#fix1

使用 webstorm 进行冲突解决

搜索Resolve Conflicts,

image.png

需要添加.gitignore, 防止多余commit

  1. 保证commit(.gitignore和dist目录会被监听改变, 其他改变都已经提交了)

  2. .gitignore添加需要忽略的目录
    dist/

  3. command + k 此时显示

    image.png

  4. git rm -r --cached .

  5. git add .

  6. git commit -m "change .gitignorefile content"

  7. 效果
    只有.gitignore的更改

    .git

2019.3.23

webstorm 快捷键

跳到命令行开头或者结尾
control + a / e

webstorm 添加 .gitignore 依然无效

  1. .gitignore添加相应文件
  2. git rm -r --cached .
  3. git add .
  4. git commit -m "fixed untracked files"
  5. 完成

websocket

  1. 代码意思
    • __dirname表示这个文件所在的电脑路径
var app = require('express')();
var http = require('http').Server(app);

app.get('/', function(req, res){
    console.log(__dirname);
    res.sendFile(__dirname + '/index.html');
});
http.listen(3000, function(){
    console.log('listening on *:3000');
});

2019.3.22

使用javascript获取响应内容

使用node发送请求内容

ssh

  1. 使用ssh远程登录别人电脑
ssh @
  1. 退出
    control + D

buffer

  1. Buffer类被引入到Node.js的API中,让其与二进制数据流的操作和交互成为可能

2019.3.21

scp命令

base 64 图片

  1. base64 编码就是可以将一副图片数据编码成一串字符串,使用该字符串代替图像地址
  2. 使用base64代替图片可以减少一个请求, 图片直接在HTML请求

linux 命令

ls -lh获得文件所有信息
2019.3.20

  1. 小的图片使用base64

需求

添加 preettier 作为统一代码风格工具

安装

使用 prettier 进行团队风格统一

安装

文件配置

  1. 创建.prettierrc
  2. 使用如下配置

2019.3.19

如何给项目添加babel-plugin?

如何给项目添加 less?

2019.3.18

英语学习

image.png

relevant 相应的

把脚手架创建的src改成app, 项目正常运行

2019.3.16

git

  • 三个概念
    1. git仓库: 有.git目录的文件夹
    2. 工作区: 除了.git目录的文件夹
    3. 暂存区
  • 重写commit信息
    git commit --amend
    

git一般工作流程

  1. 克隆代码
     git clone 
    
  2. 拉取最新代码
     git checkout master
     git pull origin master
    
  3. 新建一个分支写代码
     git checkout -b feature
     # 写代码
     git add .
     git commit -m "add feature"
    
  4. 情况1: 当天就代码写完
     git checkout master
     git merge feature
     git branch -d feature
    
  5. 情况2: 第二天才把代码写完(此时, origin/master 代码已经更新)
     git checkout master
     git pull origin master
    
     git checkout feature
     # 写代码
     git add .
     git commit -m "add feature 2"
    
     git checkout master
     git merge feature
    
     # 手动解决冲突(如果 origin/master 和本地功能分支修改了同一个文件)
    
     git branch -d feature
    
  6. 推送代码
     git push origin master:<远程feature分支名>
    
  7. 远程仓库进行 MR(merge request)
    远程master确定是否合并新的分支代码

本司 git 工作流程

  1. 在 issue 即可新建一个 branch, 并且已经起好远程分支名称
    [图片上传失败...(image-96b113-1553779783903)]

  2. 将本地代码提交到远程分支后, 需要

  3. 图片
    [图片上传失败...(image-944486-1553779783903)]

  4. 严禁一个 Merge Request 包含多个 Issue 引用或者修复多个功能。对代码审核质量控制是巨大的损害。

  5. 不要在due_date当天才延迟

  6. 一次 commit 不要同时包含图片添加,代码修改,和引入第三方库。 正确的方法为先添加资源,提交,再修改代码,再提交。

  7. 解决 BUG 的每个 Merge Request 中都应该包含: 1. 问题的原因 2. 问题的现象 3. 解决的方法。 如果有提交 Merge Request 但是没有补全这些信息,扣分!

  8. 如果delay, 需要在 issue 的 comment 写原因并@相关人员

原因:

要求调整的目标时间:

英文

  1. revert 回复

2019.3.15

工作流程

英语单词

  1. platform 平台, 如web平台, ios平台, 安卓平台
  2. reveal more choices 展示更多选项

标准commit 配置过程 配置工具过程

https://github.com/commitizen/cz-cli

  1. 全局安装
  2. 配置选项
  3. 使用

❓全局重复安装了库, 会怎么样?

Blockly

运行教育版 Blockyly 代码

  1. 克隆项目
  2. 切换下载源
    如果下载时间过长, 可以把源切换到 taobao
    yarn config get registry # 查看目前下载源
    yarn config set registry https://registry.npm.taobao.org # 切换到国内下载源
    yarn config set registry https://registry.npmjs.org # 切换到国外下载源
    
  3. 切换 node 版本(见下文)
  4. 安装依赖
  5. 启动
    yarn electron-dev
    

打包成桌面程序

  1. 生成build目录
     yarn build
    
  2. 生成dist目录
     yarn package-mac
    

如何调试

  1. 渲染进程调试和chrome调试一样, mac 打开调试窗口快捷键option + command + i
  2. 主进程调试

使用 nvm 切换当前 node 版本

  1. 安装nvm
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash
    
  2. 列出所有node版本
    nvm ls
    
  3. 安装 node 版本号, 如v8.15.1
    nvm install <版本号>
    
  4. 切换 node 版本
    nvm use <版本号>
    

目录结构

问题

[图片上传失败...(image-4db4d0-1553779783903)]
[图片上传失败...(image-3181d-1553779783903)]

配置开发环境

通过 nvm 管理 node

  1. 安装nvm
    curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash
    
  2. 列出所有node版本
    nvm ls
    
  3. 安装 node 版本号, 如v8.15.1
    nvm install <版本号>
    
  4. 切换 node 版本
    nvm use <版本号>
    

创建 React 应用

  1. 安装 React 脚手架
    npm install -g create-react-app
    
  2. 使用 React 脚手架创建一个应用
    create-react-app react-electron-app
    
  3. 安装 electron
    yarn add electron --dev
    

React 与 electron 结合

  1. 添加主进程文件public/main.js
    http://www.lejuhub.com/aelos_blockly_edu/aelos_blockly_edu/issues/420
    注意: 需要将 electron 的加载地址指向改变
     mainWindow.loadURL(`file://${__dirname}/index.html`);  // 旧
     mainWindow.loadURL("http://localhost:3000");  // 新
    
  2. package.json指定入口文件
    {
      "main": "public/main.js"
    }
    
  3. 安装 concurrently 库, 用于并行执行代码
    yarn add concurrently  --dev
    yarn add wait-on  --dev
    
    
  4. package.json添加脚本
     "electron-dev": "concurrently \"PORT=3000 BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"",
    
  5. 启动 electron 应用
    yarn electron-dev
    

2019.3.14

改需求

image.png

问题

  1. 如何通过gitlab创建一个远程分支


    image.png

    image.png
  2. 假设我要完成一个功能addPeople. (远程仓库有addPeople分支的情况)

    • 拉取远程仓库的addPeople分支代码到本地master
      git pull origin addPeople:master
    • 在本地master 进行开分支,开发,合分支, 保证addPeople代码在本地master上
      git checkout -b localaddPeople
      git add .
      git commit -m "addPeopel ok "
      git checkout master
      git merge localaddPeople
      git branch -d localaddPeople
      至此, 本地master分支有了addPeople 功能代码
    • 将本地的master推送到远程addPeople分支代码上
      git push origin master:addPeople
  3. 假设我要完成一个功能addPeople. (远程仓库没有addPeople分支的情况)
    ❓我还要拉取远程仓库的地址吗?拉取远程仓库的什么分支?

  4. TODO commit


    image.png
  5. 绿色的半天完成,搞不定需要@王松

  6. 看别人close的,可以知道如何完成一个流程

  7. http://www.lejuhub.com/carlos/softdev-department-stuff/issues?scope=all&utf8=%E2%9C%93&state=opened 为什么没有分配给我的记录?需要我自己写一个issue吗

  8. 如何使用nvm切换node版本?

    • 安装nvm
      curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash
    • 列出所有node版本
      nvm ls
    • 安装 node 版本号如v8.15.1
      nvm install <版本号>
      nvm uninstall <版本号>
    • 切换 node
      nvm use <版本号>
  9. 如何切换下载源?

    • 查看当前的下载源
      yarn config get registry
    • 切换源
      yarn config set registry https://registry.npm.taobao.org
  10. electron 入门

    • 在package.json中的main对应的文件是入口js, 在入口js经常要初始化应用, 比如指定入口html
    • 入口html指的是整个网页的入口展示, 在这里面,需要引入相应的css, img, javascript
    • 主进程 === 后端开启的server
    • 渲染进程 === 前端渲染的页面
    • 主进程与渲染进程通信
      • ipcMain 和 ipcRenderer === eventBus
      • remote 在前端(渲染进程)拿到主进程的对象, 直接调用主进程对象函数
    • 如何配置调试?
  11. ❓link rel 取值有什么区别

2019.3.13

git 常识

在 checkout 之前,必须 commit

2019.3.11

webpack 识别 svg文件 配置

  1. google 搜索 svg file loader webpack
  2. 安装相应的loader
  3. 告诉 webpack.config.js .svg文件使用我刚刚安装的loader

git 比较两个commit webstorm

如何考虑

  • 如何使用

2018.3.10

package.json 添加 scripts

  1. 原生命令是: npx webpack
  2. 写到script: "build": "webpack"
  3. 这样使用: yarn start build 相当于执行 npx webpack

在tsx中,需要安装额外的type文件

  1. 我现在在安装react-dom:yarn add react-dom
  2. 然而,我在使用react-dom库的时候,会报警告


    image.png
  3. 总结:在ts中,除了要安装相应的库,还要安装库的类型yarn add @types/react-dom --dev

yarn.lock 与 package.json 的库版本

yarn.lock

image.png

package.json
image.png

yarn.lock看version,表示这个项目用的就是16.8.4版本
package.json 只说这个项目用的是高于16.8.4版本,不一定就是16.8.4

webstorm快捷键

切换不同的文件 command + shift + ]

webpack不搜索tsx后缀文件怎么办?

  • 目前我的代码有import Button from "./button.tsx"
  • 路径是绝对没有错的
  • 错误原因: webpack没有搜索.tsx后缀的文件
  • 在webpakc.config.js 添加resolve.extensions


    image.png

将react 从react 轮子中排出 减少文件大小

webpack.config.js中添加externals

    externals: {
        react: {
            commonjs: 'react',
            commonjs2: 'react',
            amd: 'react',
            root: 'React',
        },
        'react-dom': {
            commonjs: 'react-dom',
            commonjs2: 'react-dom',
            amd: 'react-dom',
            root: 'ReactDOM',
        },
    }

webpack.config.js 如何拆分为为webpack.config.prod.js webpack.config.dev.js

  1. 新建 webpack.config.prod.js
    webpack.config.js中属于生产环境的key放到 webpack.config.prod.js
  2. package.json中的build 改成webpack --config webpack.config.prod.js
  3. 测试yarn run build

我导做的react轮子, 应该有类型声明文件(xxxx.d.tsx), 如何生成???

  1. tsconfig.json中, 添加"outDir": "dist",
  2. package.json
    main 有什么用??
"main": "dist/lib/index",
"types": "dist/lib/index",

高阶组价

  1. 高阶组件是一个函数, 作用是接受一个组件, 返回出一个新的组件
  2. 高阶组件作用
    • props劫持

2019.3.9

diff 算法 原理

  1. 生成一个对象dom,需要三个东西:标签名称 标签属性 标签子标签
  2. 新旧dom树比较过程
    1. 对新旧两棵树进行深度优先遍历,给节点一个唯一的标记
    2. 在深度优先遍历的同时,对新旧节点进行比较,如果有差异的话,记录到 patches 对象中
    3. 根据patches对象,实际操作dom

key 为什么要 因为react不知道增删改查情况

[{name: "rao"},{name:"jia"}]  变成  [{name: "hi"},{name:"jia"}] 
有两种可能
1. rao 变成 hi
2. rao 变成 jia     jia 变成hi
如何防止这种情况? 加key,比较的时候先看key

es6 新数据类型 symbol

  1. 为什么要有 symbol =>对象中,防止key值相互覆盖
  2. symbol 类似于字符串的数据类型
  3. symbol用法
// 声明一个symbol
let mySymbol = Symbol();
let mySymbol1 = Symbol();

// symbol不一样
console.log("两个新的symbol可能一样吗", mySymbol === mySymbol1)
// 把symbol放到对象中
let obj = {}

// 第一种写法,在对象声明的时候添加symbol
obj = {
 [mySymbol]: "1"
}

// 第二种写法,追加symbol
obj[mySymbol1] = "2"

// 读取symbol 的时候,必须使用[]
console.log(obj[mySymbol])

console.log(obj)

新数据结构set map symbol

  1. symbol 把他当成一个字符串就行了,并且不会和任何字符串重复,这个字符串只能通过变量获取
  2. set 没有重复的数组 通过[...new Set([1,2,1,1,])]生成数组
  3. map 更加灵活的对象,key 不仅仅是字符串

模块化发展历史

  1. 直接打印1
  2. 「直接打印1」设为一个函数,挂载window,等待其他模块执行这个函数(实现模块控制)
  3. 在这个模块内声明变量,并且这个变量只能在这个模块使用
    • 立即执行函数
    • let

2019.3.8

react 面试 受控组件 vs 非受控组件

  1. input为例子,受控组件 === input html
  2. 受控组件指的是input加了value,react 官方推荐
  3. 不受控组件指的是input不加value,直接操作dom,优点是容易和第三方库结合
  4. 不懂非受控组件
    直接通过ref就可以获取inputdom了

如何将事件对象 传给自定义的回调函数 input 透传给自定义回调函数 表单

https://codesandbox.io/s/km79kv5kxo

2019.3.7

虚拟 DOM 原理

  • DOM操作的发展历史
    1. 直接在回调函数操作 DOM
    2. 使用 MVC 架构,换个地方操作 DOM
    3. 使用 MVVM 架构
      状态变更->重新渲染整个视图
      缺点:
      • 状态变更都要重新构造整棵 DOM,性价比太低
      • input和textarea的会失去原有的焦点
    4. 小结:MVVM 的思路是对的:维护状态,更新视图,但是实现方法需要更加精细(借助虚拟 DOM + Diff 算法,修改变化的 DOM )

--- 最新的放到上面

9.11

  1. 使用 API 管理工具, 后端返回的数据要使用接口定义.
  2. 在style component中, 自定义css组件值

9.12

  1. 使用git多人协作
  2. 使用style component自定义css值

9.13

  1. 还是多人协作, 能在分支上写代码, 合并到主分支上
  2. 一个算法: http://jsbin.com/xaduhajewe/edit?html,js,output

9.19

  • 更新stylecomponent到最新版本

    1. yarn info style-component version获得最新版本
    2. package.json手动修改版本
    3. yarn安装最新版
  • typescript 自定义接口继承 typescript 内部接口

    1. 变量 flowInfo 符合接口 IStageInfo ,并且 flowInfo 是一个数组,IStageInfo 接口定义如下:
    interface IStageInfo{
       id: string;
       upgrade_id: string;
       stage_id: string;
       stage_name: string;
       start_time: string;
       end_time: string;
       executor_id: string;
       stage_status: string;
       is_delete: string;
    }
    

    此时使用数组方法, 报错, 信息为Property map does not exist on type IStageInfo, 需将接口继承数组接口

    interface IStageInfo extends Array {
       id: string;
       upgrade_id: string;
       stage_id: string;
       stage_name: string;
       start_time: string;
       end_time: string;
       executor_id: string;
       stage_status: string;
       is_delete: string;
    }
    

9.20

  • 翻译


    image.png
    1. parameter函数定义参数,argument函数调用实际参数。
    2. 实际参数dataObj.key是string, 而indexOf需要传入一个number
  • 如果一个接口是这样的, 接口地址www.baidu.com?name=1&age=2&grade=3 ,那么使用一个obj, 用于改变接口地址的query值,
  • 路径的快速引用
    引用文件

    被引用文件

    引用文件中 import Api from "../../../library/Api.tsx"
  • tspescript 枚举
    例子
  • es6 对象的key是变量 文档

9.25

  • 静态作用域与动态作用域
    1. 作用域用于确定如何找变量
    2. 静态作用域 = 函数定义位置找变量
    3. 动态作用域 = 函数调用位置找变量
    4. 例子
    var value = 1;
    function foo() {
        console.log(value);
    }
    function bar() {
        var value = 2;
        foo();
    }
    bar();
    
    静态作用域执行过程: 
    1. 执行 bar()
    2. 转到 bar 函数定义的位置, 执行 bar 函数内容(也就是声明变量 `var value = 2`)
    3. 执行 foo()
    4. 转到 foo 函数定义的位置, 执行 foo 函数内容
    5. 打印 value 变量, 需要寻找 value
    6. **定义 foo 函数没有 value, 外面找**
    7. 找到了, var value = 1
    
    动态作用域执行过程: 
    1. 执行 bar()
    2. 转到 bar 函数定义的位置, 执行 bar 函数内容(也就是声明变量 `var value = 2`)
    3. 执行 foo()
    4. 转到 foo 函数定义的位置, 执行 foo 函数内容
    5. 打印 value 变量, 需要寻找 value
    6. **调用 foo 函数有 value**
    7. 找到了, var value = 2
    
  • 执行上下文
    1. 执行一个函数, push 这个函数的[执行上下文]到[执行上下文栈]
    2. 完成[执行一个函数], [执行上下文栈] 执行pop
    3. 例子
      function fun3() {
        console.log('fun3')
      }
    
      function fun2() {
        fun3();
      }
    
      function fun1() {
        fun2();
      }
      fun1();
    
  • 变量对象 === 存储了定义的变量和函数声明
  • 作用域 === 是一个范围, 用于确定如何查找变量
  • 执行上下文栈(ECStack) === 是一个数组, 浏览器管理函数执行的途径
  • 执行上下文(EC) === 是一个对象, 遇到函数执行就会激活这个函数创建它的执行上下文, 包含 变量对象, 作用域链, this, 范围是函数{}包含的部分
  • 变量对象 === 是一个对象, 保存了某个范围定义的变量和函数声明
  • 作用域链 === 是一个数组, 保存父变量对象, 用于查找变量
  • 一旦将执行上下文压入到 stack , 就会进入到执行上下文的创建阶段
  • 执行上下文的创建阶段要做的事情

执行上下文

  • 执行上下文 === 执行环境
  • 当浏览器遇到函数执行的语句, 会创建这个函数的执行上下文(EC, 函数执行的环境),并且通过栈(先进后出)来处理函数执行顺序问题,
  • 包含变量对象, 作用域链, this
  • 在函数执行语句(标志: xxx())将这个函数的EC push 到栈
  • 在执行完函数(标志: 函数声明内主动return or return undefined)后将这个函数的EC pop 出来
  • 执行上下文的生命周期: 创建阶段(浏览器粗略的扫一眼代码) + 代码执行阶段(浏览器一句一句执行代码)
  • 创建阶段 === 创建变量对象 + 建立作用域链 + 确定this的指向。
  • 代码执行阶段 === 变量赋值 + 函数引用 + 执行其他代码。
  • 执行上下文初始化要做的事情

变量对象

  • 创建变量对象的过程如下:
    1. arguments对象
    2. 函数声明, key 是函数名称, value 是函数的内存地址的引用. 若函数名重复, value会被最新的引用覆盖
    3. 变量声明, key 是变量名, value 是 undefined, 如果变量名与函数名重复, value 不是为undefined, 而是跳过这个变量声明.
  • 代码执行过程, 这个就很正常的啦
  • 当函数被执行, 一个活动对象(由arguments初始化而成)被创建并分配给执行上下文, 随后, 这个活动对象被当成变量对象用于变量初始化

作用域与作用域链

  1. 作用域 === 范围, 函数{}包含的代码
  2. 作用域链 === 数组, 数组的item是变量对象,用于有序的访问变量与函数

闭包

  1. 闭包 === 对象 = [执行上下文AAAA] + 该执行上下文创建的[函数BBBB]
  2. 如果BBBB使用了AAAA内的变量, 闭包就产生了

this

  1. this在执行上下文的创建阶段指定, 也就是说在函数执行(调用)的时候才知道 this 是谁.
  2. 函数执行(调用)有三种方法 ,画图

内存空间

  • 堆内存(heap) 栈(stack)
  • 三种数据结构的特点
    1. 堆(heap): key:value无序
    2. 栈(stack): 单出口, 先进后出
    3. 队列(queue): 双出口, 先进先出 事件循环要用
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();

函数执行过程

  • 当浏览器执行一个函数xxx(), 执行以下几步
    1. 浏览器执行xxx(), 就进入xxx的作用域
    2. 将 [xxx的执行上下文] 压入栈
    3. 建立xxx的执行上下文
      • 创建过程(浏览器粗略扫一眼代码)
        1. 设置 key 为 scopeChain , value 是 xxx 函数的所有父级执行上下文的变量对象
        2. 设置 key 为 variable Object , value 是 arguments + 函数声明 + 变量声明
        3. 设置 key 为 this , value 的取值有一定规则
      • 代码执行过程(浏览器一行一行执行代码)
        1. 将变量对象进行赋值, 此时的变量对象叫做活动对象
        2. 将这个活动对象放到作用域链的最前面
        3. 遇到return语句, 将 xxx 的执行上下文从栈pop出来
      • 获得 xxx 的执行上下文, 包含3个key, 分别是作用域链, 变量对象, this

几个概念定义

  • 作用域(context)
    1. 就是一个范围, 如function(){ 这里面是一段作用域 }
    2. JavaScript 使用的叫词法作用域(静态作用域), 静态作用域与动态作用域的区别:
      如何确定作用域?
      静态作用域 = 函数定义位置是作用域
      动态作用域 = 函数调用位置是作用域
    var value = 1;
    function foo() {
        console.log(value);
    }
    function bar() {
        var value = 2;
        foo();
    }
    bar();
    
      静态作用域执行过程: 
        1. 执行 bar()
        2. 转到 bar 函数定义的位置, 执行 bar 函数内容(也就是声明变量 `var value = 2`)
        3. 执行 foo()
        4. 转到 foo 函数定义的位置, 执行 foo 函数内容
        5. 打印 value 变量, 需要寻找 value
        6. **定义 foo 函数没有 value, 外面找**
        7. 找到了, var value = 1
     动态作用域执行过程: 
        1. 执行 bar()
        2. 转到 bar 函数定义的位置, 执行 bar 函数内容(也就是声明变量 `var value = 2`)
        3. 执行 foo()
        4. 转到 foo 函数定义的位置, 执行 foo 函数内容
        5. 打印 value 变量, 需要寻找 value
        6. **调用 foo 函数有 value**
        7. 找到了, var value = 2
    
  • 执行上下文(ExecutionContext, 又叫执行环境)
    1. 你可以当成一个对象, 通过 [执行上下文] 和 [执行上下文栈] 结合, 浏览器可以控制函数的执行顺序
    2. 执行上下文有 3 个 key ,
      • 作用域链
      • 变量对象
      • this
  • 作用域链
    1. 可以当成一个数组, 第一项是 [本执行上下文的变量对象] , 用于作用域中的变量与函数寻找规则.
  • 变量对象
    1. 可以当成一个对象 , 他的 key 由以下 3 种组成
      • arguments对象
      • 函数声明, key 是函数名称, value 是函数的内存地址的引用. 若函数名重复, value会被最新的引用覆盖
      • 变量声明, key 是变量名, value 是 undefined, 如果变量名与函数名重复, value 不是为undefined, 而是跳过这个变量声明.
  • this
    1. 就是对象, 重点是如何确定 this 是谁, 我的方法如下

9.26

  1. arguments
    • 类数组转成数组
      let arrayLike1 = {0: "apple", 1: "banana", 2: "pink"}
      let arrayLike2 = {0: "apple", 1: "banana", 2: "pink"}
      let arrayLike3 = {0: "apple", 1: "banana", 2: "pink"}
      let arrayLike4 = {0: "apple", 1: "banana", 2: "pink"}
      let arrayLike5 = {0: "apple", 1: "banana", 2: "pink"}
      
      
      Array.prototype.slice.call(arrayLike1)
      Array.prototype.splice.call(arrayLike2, 0)
      Array.prototype.concat.call(arrayLike3, [], arrayLike3)
      Array.from(arrayLike4)
      let array5 = {...arrayLike5}
      
      console.log(arrayLike1)
      
    • call apply bind 区别
      1. 都是用来改变函数中this的指向
      2. call 和 apply 改变指向后立刻执行, bind 返回一个新函数, 函数内的this是bind的第一个参数
      3. call 的参数传递是一个一个的
      4. apply 的参数传递只能是一个数组
      5. 最简单的bind实现
        Function.prototype.bind = function(ctx) {
            var fn = this;
            return function() {
                fn.apply(ctx, arguments);
            };
        };
        

9.27

tooltip

9.28

  1. webstorm 使用技巧 比较两个文件的异同


    image.png

    context menu === 文件的路径

  2. ts报错


    image.png

    assign to === 修改

  3. react 数据保存
    https://jsbin.com/yutotumese/edit?html,js,output
  4. react setState
    https://jsbin.com/vaqatutago/edit?html,js,output
  5. 函数返回的问题 为什么返回undefined
    https://jsbin.com/yisebejela/edit?html,js,output

9.29

  1. ts 不工作了 通过[ctrl + 点击]激活ts
  2. 外部引入的库, 库的 css 无法加载, 是 webpack 的配置问题
  3. webpack.config.js
    image.png

    如果为true, 那么css文件的[class名称]一定会通过hash值转码
    如果设为false, 那么css文件的[class名称]一定不转码
  4. 两种引入方式的区别
    import xx from "codemirror/lib/codemirror.css"
    import from "codemirror/lib/codemirror.css"
    前者相当于创建一个然后把文件的内容都放到标签内
    后者相当于创建一个对象, 对象的key是 css 文件的 className, value 是[经过转码的字符串], 仅当module设为true才有效果
  5. http://js.jirengu.com/jomiwagete/1/edit?html,css,js,console,output 创建一个新的obj, 他的值从旧的obj来

9.30

  1. forEach 处理item是对象, 直接在原对象操作 http://js.jirengu.com/quvoxeqiju/1/edit?js,console,output
  2. react 组件有问题, constructor初始化一个数据,假设为this.state.number = 0,然后render就直接使用了这个初始化的数据,然而在componentWillMount的时候,会改变这个数据,假设为this.state.number = 1111, 我们使用的也是这个改变之后的数据, 该怎么办?
    react 的生命周期
  3. webpack的alias 和 在ts中使用webpack设置的alias不报错
    1. __dirname表示整个项目的名称, 应该是绝对引用


      image.png
  1. 使用typescript, 需要在定义变量时定义数据类型
    1. 定义showData


      image.png
    2. 在setState中使用showData, 报错
      image.png

      注意这句话Type ' {panes: ICmdObj[];} is not assgnable to type "IFormData" '说明ts不知道showData的数据结构, 所以要这样写
    3. 定义showData的接口


      image.png
    4. 在定义showData变量的时候, 需要定义其数据类型


      image.png
    5. 总结: 在定义变量的时候注意定义其数据类型
  1. let 和 const ts 报错


    image.png

    ts是对的,我是错的, cmd保存地址, 并且cmd一直没有变化

  2. 什么地方需要定义接口?

      let a: number = 1  // ①定义变量
      function add(a: number, b: number): number{ // ②参数 ③函数返回
          return a + b
      }
      const bbbb: number = add(1, 2) // 定义变量
      console.log(bbbb)
    

10.8

  • webpack 和 typescript 配置alias
    目录结构
    image.png

    不使用aliasimport Api from "../../../library/Api"
    若使用aliasimport Api from "@/library/Api";
    webpack
     module.exports = {
     //...
     resolve: {
      alias: {
        "@": path.resolve(__dirname, './src/'), // 以webpack.confi.js初始地址
       }
     }
    };
    
    tsconfig
      {
       "compilerOptions": {
       "baseUrl": "./", // 以tsconfig.js为初始地址
       "paths": {
         "@/*": ["src/*"]
       },
       }
    
  • 这个typescript报错如何解决??
    例子

10.15

  • 遇到一个简单的算法题, 搞了快两个钟,心态有点蹦,记录一下例子
  • 自己写react-router的第一个例子
    1. === div
    2. === a
    3. 根据url,展示相应组件,
    4. exact的意思 === 只有当url与的path属性完全一样,才会展示的component组件
    
    
    如果 url 是/home/jfdkjfdksaljklfdsa
    组件Xxx能通过this.props.match拿到相应的 home 和 jfdkjfdksaljklfdsa

10.16

  1. for循环无效??例子
  2. 就是 只不过自动点击了

10.17 看了方方的数组操作的视频 废弃 完全么有吸收

  1. slice怎么就可以将伪数组变成数组呢??? 例子
  2. 伪数组转成真数组的方法
  3. 变量互换 es6
  4. 数组操作 除了 4+ 3 ,其他的操作都需要[return + 拿变量去接]
  5. slice sort 的源代码
  6. sort方法处理对象数组
  7. 用map代替forEach
  8. 七个数组的源代码
  9. undersocre

10.17 bind

  1. call 和apply 是直接调用函数, bind返回一个新函数
  2. for循环边界控制

10.18

  1. 里面放, 一旦有一个匹配, 就不继续往下看了
  2. 构建报错
    image.png

    简单来说
    package.json文件下
    image.png

    windows系统识别不出&&
    添加包cross-env
    NODE_ENV=xxxx前添加 cross-env即可 (截图已经添加了)
  3. 文件目录
    yapi/server后端代码
    yapi/client 前端代码
    yapi/common 前后端都可以使用代码

10.19

  1. server/controllers/group server/models/group server/service/group 这三个文件需要阅读, 这三个文件都是实现项目分组的功能, 只不过分开了
  2. server/controllers/group
    装饰器的作用: 帮助我们处理大部分非逻辑代码!
    修改类, 方法, 属性
    装饰器其实就是一个函数,函数的返回值还是一个函数
  3. async await
    • async 表示函数里有异步操作,async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。
    • await 表示紧跟在后面的表达式需要等待结果。当函数执行的时候,一旦遇到 await , 等到触发的异步操作完成(拿到await后面的返回值),才接着执行函数体内后面的语句。
  4. 代码


    image.png

    红框函数的作用: 规定后端返回给前端的数据格式

  5. image.png

    当前脚本文件所在目录下的电脑路径(路径名称包含d盘之类的)

  6. linux 项目可以使用, 在win上不能使用的其中一种情况
    报错情况

    寻找webpack.config.jsinclude打印路径
    设置的路径

实际的路径

在win下,/就是错的, 所以修改include
修改include

  1. 后端如何debugger
    • package.json找到后端的启动脚本, 复制它
      image.png
    • 安装编辑器的node


    • 按照下图进行配置


      image.png
  2. 已知前端接口路径,如何找到相应的后端文件?
image.png
image.png
  1. 报 504 错误 ===

10.22

  1. debugger

    • f8表示一行一行执行, 遇到函数直接跳过, 得到函数的结果
    • f7表示一行一行执行, 遇到函数, 进入到函数内部, 继续执行函数内部的语句
  2. 提交commit

    • feat: 新特性
    • docs: 文档修改
    • test: 测试用例修改
    • chore: 其他修改, 比如构建流程, 依赖管理.
  3. 装饰器 阮一峰

      @decorator
      class A {}
    
      // 等同于
    
      class A {}
      A = decorator(A) || A;
    

10.23

  1. graphQL是什么

    graph + QL = graph 图形化的 query 查询 language 语言

  2. 感性认识(与restful比较)

    • graphQL 可以自由定制后端返回的数据结构. 比restful更加灵活

    • graphQL 的查询参数就是后端后端返回的数据结构

  3. 同步与异步区别

      function printString(string){
        setTimeout(
          () => {
            console.log(string)
          }, 
          Math.floor(Math.random() * 100) + 1
        )
      }
      function printAll(){
        printString("A")
        printString("B")
        printString("C")
      }
      printAll()
    

    同步: 等待printString("A")完成之后, 才执行接下来的代码
    异步: 等待同步代码printAll()执行完之后, 往任务队列中添加三个定时器, 代码执行根据时间而定

    如果我们想让他按照A B C的顺序打印, 就必须使用callback promise Async/awit

  4. 例子

    random例子
    callback修复例子
    promise修复例子
    await修复例子
    await传数据

10.24

  1. 困扰了两天的问题:

    两个模块a, b, 引用同一个模块test.js, 但是a模块可以顺利使用test.js,而b模块就不行。
    看模块的使用方式

  2. try catch 的语法,例子

  3. identifier 和 variable 的区别

    image.png

10.25

  1. 重构代码(有参考代码)

    • 复现待重构代码功能

    • 使用/**/注释旧代码 通过alt + down 实现函数之间跳转

    • Ctrl + D比较参考代码与旧代码

    • 看旧代码, 有什么报错

10.26

1. 这两个params有什么区别??

    ![image.png](https://upload-images.jianshu.io/upload_images/5529438-3e534f38bbad4dbf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

10.29

  1. 第二个项目: 重构全栈项目的interface模块

    • 目标: 使用ts将interface模块的请求内容的数据结构写清楚

    • 目标: 使用ts将interface模块的响应内容的数据结构写清楚

  2. 解构赋值, 可以对其解构出来的数据进行改名字例子

10.30

  1. 打断点, 不能打在函数的命名位置, 打在函数内部

  2. 打断点, 如果想知道变量的值, 打在变量之后

  3. call / apply模拟实现

    • 作用: 调用函数时, 确定 this 的指向 === this 就是使用 call 方法调用的第一个参数

    • 例子

    • 模拟实现 call

    • 问题

10.31

  1. 同步与异步, 单线程与多线程, 回调函数, promise, await

10.5

端口占用 bug 解决过程

image.png

我在这里点了 disconnect

重新开启项目, 后端报错

image.png

端口3001已经被占用了

image.png

重启

try catch 语法使用

例子
总结: ①throw === return; ②遇到 throw , 找 catch 语句, 并且 catch 的变量就是throw的值

11.6

detach header

image.png
image.png
image.png
image.png
image.png

同步与异步

后端 MVC 的 controlller 层的作用

通过接口获取数据, 将数据进行解析, 传给 server 层

server 层完成完成相应数据的逻辑处理, 将最终数据return出来

controller 层对 server 层数据传来的数据进行

11.7

typescript 如何让一个变量既可以是 number 又可以是 string , 并且默认值是 10 , 在使用的地方根据变量的类型使用相应的类型

异步与同步

11.8

如何在 a 类中使用 b 类的方法

例子

11.12

将list_cat与list合并

将controller/interface的list_cat函数去除

根据params给list传入不同的参数(service/controller中的list)

async list(page: number, limit: any, uid: number, searchId: ISearchId): Promise {
    if (searchId.catid) {
      // 根据catid搜索接口
      const catid = searchId.catid
      const catdata = await this.catModel.get(catid);
      const project = await this.projectModel.getBaseInfo(catdata.project_id);
      if (project.project_type === 'private') {
        if (await this.authorizeService.checkAuth(project._id, 'project', uid, 'view') !== true) {
          throw new ResError('没有权限', 406);
        }
      }
      const result = await this.Model.listByCatidWithPage(catid, page, limit);

      const count = await this.Model.listCount({ catid });

      return {
        count,
        total: Math.ceil(count / limit),
        list: result,
      };
    } else {
      // 根据projectId搜索接口
      const projectId = searchId.projectId
      const project = await this.projectModel.getBaseInfo(projectId);
      if (!project) {
        throw new ResError("不存在的项目", 407);
      }
      if (project.project_type === 'private') {
        if (await this.authorizeService.checkAuth(project._id, 'project', uid, 'view') !== true) {
          throw new ResError("没有权限", 406);
        }
      }
      if (!projectId) {
        throw new ResError("项目id不能为空", 400);
      }

      try {
        let result;
        if (limit === 'all') {
          result = await this.Model.list(projectId);
        } else {
          result = await this.Model.listWithPage(projectId, page, limit);
        }
        const count = result.length;

        await emitHook('interface_list', projectId).then();

        return {
          count,
          total: Math.ceil(count / limit),
          list: result,
        };

      } catch (err) {
        throw new ResError(err.message, 402);
      }
    }

  }

根据传入的数据, 其中if之后是原list_cat的参数
else之后是原list的参数

image.png
image.png

ISearchInterfaceObj 为什么不能放到另一个文件中??

文件interfaceList中, ISearchInterfaceObj 接口只能在本文件定义, 如果使用了文件commonInterface.ts的接口就报错.
可以, 重启一下前端构建工具就行

如何使用 interface+ enum 定义一个数据结构

现有如下数据结构

{
  path: "123321",
  projectId: 123321,
}

{
  path: "123321",
  catid: 123321,
}

要求是写一个接口, 只能有两个key, 其中第二个key只能是projectId或者catid, 并且projectId与catid只能有一个.

11.15

正则删除所有console console.log.*

搜索功能实现

  1. 前端有一个 input 和 日期选择器, 用于收集用户搜索信息A对象. onChangeSearch
    image.png

    image.png
  2. 点击搜索时, 第一步是将A对象中的falsy值去除
  3. controller/interface


    image.png

11.19

graphQL

graphQL组成:

  1. schema(类型)
  2. operation type(动作) : 从服务器想拿什么数据
  3. resolvers(解析器): 告诉助理怎么拿数据

npm -D

npm: 开发时用到, 发布时用到
npm -D: 开发时用到, 发布时不用

11.22

  1. react 组件获取数据的最佳方式

12.3

  1. 我想干嘛??
    仅仅写一份文件(json, yaml 是描述 api 的语言), 并且通过 oas 描述 api. 这样能使用swagger生成前端, 后端的接口文档.

  2. oas 是描述 restful api 的规范, 用于描述 api

  3. oas(json表示), 实际是规定了key的json, 从这里看规定了什么key

  4. raml(restful api modeling language) 塑造 restful 的语言
    用于设计api

  5. redux

    • reducers.js 用于保存初始数据 + 修改数据

12.4

今日任务

  1. openApi / RAML 用自己的话说一下用处
    • oas === openApi specification === 如何描述 api 的一种规范, 实际上就是 规定了特殊key的json
      并且通过 swagger 来表现
    • RAML === Restful Api Modeling Language === 构建 restful 的语言
    • oas / RAML 关系: 都是为了管理 restful api 的一种规范, 两者是竞争关系, 作用都是为了描述restful api的作用
  2. 理清redux + react-redux 的数据传递思路
    • 写action, 用于告诉 redux 改变什么数据.
    • 写reducer, 根据action, 具体改变数据的地方.
    • 在index.js中初始化数据 + 传递数据给app (通过createStore 和 Provider)
    • 在app组件中, 通过connect将数据传给app

12.5

  1. intel lij 覆盖commoit


    点击这个, 将覆盖上一次的commit
  2. restful参数的四种表现形式
    • Header parameters
    • Path parameters
      /service/myresource/user/{user}/bicycles/{bicycleId}
    • Query string parameters
      /book?title=xxx
    • Request body parameters
      {"days": 2,"units": "imperial","time": 1433524597}
  3. raml 将http请求的request-header放到了body内??
  4. raml type使用
定义type
types:
  song: |
    {
      "type": "object",
      "$schema": "http://json-schema.org/draft-03/schema",
      "id": "http://jsonschema.net",
      "required": true,
      "properties": {
        "songTitle": {
          "type": "string",
          "required": true
        },
        "albumId": {
          "type": "string",
          "required": true,
          "minLength": 36,
          "maxLength": 36
        }
      }
    }
使用type
body:
  application/json:
    type: song
    example: |
      {
        "songId": "550e8400-e29b-41d4-a716-446655440000",
        "songTitle": "Get Lucky",
        "albumId": "183100e3-0e2b-4404-a716-66104d440550"
      }
相当于
body:
  application/json:
    type: |
      {
        "type": "object",
        "$schema": "http://json-schema.org/draft-03/schema",
        "id": "http://jsonschema.net",
        "required": true,
        "properties": {
          "songTitle": {
            "type": "string",
            "required": true
          },
          "albumId": {
            "type": "string",
            "required": true,
            "minLength": 36,
            "maxLength": 36
          }
        }
      }
    example: |
      {
        "songId": "550e8400-e29b-41d4-a716-446655440000",
        "songTitle": "Get Lucky",
        "albumId": "183100e3-0e2b-4404-a716-66104d440550"
      }

12.13

  1. 关系型数据库 === excel

12.18

react 切换tab不更新数据处理方法

componentDidUpdate

react props数据需要修改 可以修改吗? 在哪修改? 不能修改的话应该怎么处理?

不可以修改props数据

react 数据来源:

  1. 通过 axios 请求获得的数据, 放到state中, 可以在拿到请求的数据之后修改
  2. 通过redux传过来的数据A, 如果想修改数据A, 请在redux中修改
  3. 通过父组件传过来的数据, 不知道怎么处理

forEach + await 失效 不起作用

12.19

每天早上要拉代码: git pull <远程仓库, 一般是origin> <本地仓库, 一般是分支名称如openapi>

每天下班要push 代码: git push origin openapi

我买了新电脑,如何在新电脑往公司的仓库下载公司代码,提交代码??

  1. 在公司提供的github(gitlab)中添加ssh
  2. git clone 即可

这个错误怎么处理?? You should not use or withRouter() outside a

字面意思: 你不能再组件之外使用或者withRouter()


第二个指示应该放到第一个指示之内

12.20

全栈项目 如何开启后端 使用intel lij 上面有

intel lij 如何安装插件(插件是压缩的 zip格式)手动下载插件

  1. https://plugins.jetbrains.com/搜索需要的插件
  2. 双击shift 搜索plugins 选择从disk导入插件
  3. 注意版本号

如何安装 启动 mongodb

  1. 安装# Homebrew
    image.png

全栈项目 mongodb 搭建后端服务

  1. 使用Intel lij 开启后端服务 上面有
  2. 安装mongodb
  3. 打开, 确认mongodb服务开启


    image.png
  4. 查看项目的app.js, 目的是查找项目连接数据库的名称


    image.png
  5. 在开启mongodb的位置,
  • show dbs 查看当前所有db
  • use 数据库名称 =》 新建一个数据库
image.png

2019.3.7

生命周期 react

  1. react 的生命周期(最常用)
    • 挂载:constructor => render => componentDidMount
    • 更新:render => componentDidUpdate
    • 卸载:componentWillUpdate
  2. 组件经常要做的操作
    • 请求数据(ajax)
      componentDidMount
    • 更新数据(setState)
      只能在事件监听函数或者componentDidMount
  3. 为什么shouldComponentUpdate重要?
    • 自定义更新组件
    • 提高react性能
  4. setState时,会执行那些钩子函数?
    getDerivedStateFromProps => shouldComponentUpdate => render => getSnapshotBeforeUpdate => componentDidUpdate

路由 react 历史

  1. react-router目的: 无刷新的条件下切换显示不同页面
  2. 怎么实现
    1. 找到一个api,它能无刷新的改变url
    2. 监听url的变化,根据url的数据展示不同的页面
  3. 什么api能无刷新的改变url?
    • hash路由
      • window.location.hash='edit'改变url
      • edit
    • html5 history
  4. react-router-dom常用组件

react 传递函数定义,并且这个函数带参数

使用箭头函数定义 + 执行原函数,附带参数即可
https://codesandbox.io/s/5wp3z4mk0n

react 数据流动 历史

  1. 直接通信 父子
    • 父传子:通过props
    • 子传父
      1. 父组件通过props传一个函数
      2. 子组件执行这个函数,带上参数
  2. 通过eventBus
    1. 父组件监听事件
    2. 子组件触发事件
  3. redux
    1. 编写reducer函数,用于初始化数据和数据修改
    2. 生成store
    3. 监听数据,一旦数据变化,重新render
    4. 从上往下传递store
    5. store有获取数据和修改数据接口,使用即可
      redux数数例子
  4. react-redux
    1. 编写reducer函数,用于初始化数据和数据修改
    2. 生成store
    3. 使用组件包裹整个组件,并且传store给
    4. 在子组件,获取和修改数据,需要分别创建函数,通过connect连接ori

你可能感兴趣的:(每日学习)