自己实现 React-Redux (六):去除 context 依赖,实现 provider
Index 组件中的 context 依赖Content 组件、Header 组件以及 ThemeSwitch 组件都是依赖于 Index 父组件的 context 属性,而 context 属性在 Index 组件中存在会导致 Index 依赖于额外的属性,扩展性不强。
因此我们需要提炼出一个淡出的组件 provider 来当作 Index 的父组件,来存储全局的 context 属性,实现 Index 组件与 context 属性的解耦。
构建 Provider 组件在 src/react-redux.js 文件中添加如下代码:
12345678910111213141516171819202122232425class Provider extends Component { static propTypes = { store: PropTypes.object, children: PropTypes.any } static childContextTypes = { sto ...
自己实现 React-Redux (五):实现 mapDispatch2Props
dispatch 的代理工作在 src/ThemeSwitch.js 中,ThemeSwitch 组件通过 store 的 dispatch 方法实现了数据的更改,这也导致了组件的强耦合。
我们的思路是让高阶组件 Connect 代替 ThemeSwitch 来实现 dispatch 功能,同时通过 props 将方法传递给 ThemeSwitch 组件。
修改 src/react-redux.js文件:
12345678910111213141516171819202122232425export const connect = (mapState2Props, mapDispatch2Props)=>(OriginComponent)=>{class Connect extends Component { componentWillMount(){ this._updateProps() } _updateProps(){ const {store} = ...
自己实现 React-Redux (四):connect 和 mapState2Props
子组件直接利用 context 的问题第三节我们实现了子组件利用 context 属性,通过统一的修改方式对全局 state 进行修改,同时利用发布者-订阅者模式实现了数据更新的监听及界面重新渲染。
但是仍然存在两个问题:
子组件都是利用 context 属性来取得 store 对象,进而对全局状态 state 进行修改,这样会导致很多重复性代码。
每个子组件都依赖了 context 属性,导致子组件与父组件形成了强耦合,不利于组件的复用。例如,前面的 Context 组件需要父组件定义 context 属性,否则主题颜色将无法设置。
解决方法:
对于重复使用的代码,可以凝练提取出一个可复用的代码结构。这里可以通过高阶组件(或者装饰器模式)将 context 的控制与相关事件监听代理起来。
对于强耦合问题,可以通过设置 Pure Component,即在高阶组件内部的被装饰组件尽量设计成纯组件。纯组件是其状态仅依赖于父组件传入的 props 以及 自己的 state,对于外界依赖极低,因此复用性极高。
抽离出公共的逻辑代码我们可以设计一个 connect 函数,该函数的 ...
自己实现 React-Redux (三):结合 context 和 store
构建 createStore 函数实现 Redux 架构原理: 构造一个函数 createStore,该函数可以对全局变量的状态进行统一的管理。该函数传入一个全局 state 以及状态修改纯函数 reducer, reducer 定义了改变状态的逻辑并返回一个新的状态,为后面的动态渲染优化做准备。
在 src/index.js 中加入 createStore 函数
12345678910111213141516171819202122232425262728293031323334353637function createStore(reducer){ // 初始状态 let state = null // 定义发布者 const listeners = [] // 绑定订阅者 const subscribe = (listener)=>listeners.push(listener) // 获取 state const getState = ()=>state // 绑定处理函数 const dis ...
自己实现 React-Redux (二):初始化工程
构建项目在命令行依次输入以下命令
12// 利用脚手架创建新项目npx create-react-app react-redux
12// 安装类型检查依赖npm install --save prop-types
创建文件安装好后在 src/ 目录下新增三个文件:Header.js、Content.js、ThemeSwitch.js。
修改 src/Header.js:
1234567891011121314import React, { Component } from 'react'import PropTypes from 'prop-types'class Header extends Component { render() { return ( <div> <h1>动手实现React-Redux</h1> </div> ) } ...
自己实现 React-Redux (一):React.js中的 context
Redux架构Redux是一种前端架构,是由 Facebook 的 Flux 框架演变而来,但避开了 Flux 的复杂性。而 Flux 是一种模式而非正式框架,通过利用单项数据流补充React的组合视图组件。
Redux要解决的问题React的数据流是单项数据流,如果任何一个子组件依赖了父组件的状态,就需要将状态存储到父组件中进行状态提升。但假设该父组件又是另一组件的子组件且状态又由另一组件决定,那么状态又需提升至另一组件。层层的状态依赖非常麻烦。
React中可以通过设置 context属性实现全局变量的效果,任何该组件的子组件都可以读取到 context 属性;而一旦 context 属性改变,所有依赖 context 属性的组件都会更新。
并且所有能读取到 context 的组件都可以对该属性进行修改,如果在组件关系非常复杂,到处存在这种修改父组件 context 的逻辑,那么可能产生难以预测的后果。
因此 Redux 规范了修改全局属性 state 的方法,便于状态改变的维护与管理。
核心概念1. 单一数据源
整个应用的 state 被储存在一棵 object tree 中,并 ...
用JS写算法
用JS去除字符串前后空格1234567891011121314151617181920212223242526272829function trim(str){ if(!str) return ""; return trimRight(trimLeft(str));}function trimLeft(str){ // 判断字符串(去掉换行、tab等) const judgeStr = new String(" \t\r\n"); if(judgeStr.indexOf(str.charAt(0))!==-1){ let j = 1, len = str.length; while(j<len && judgeStr.indexOf(str.charAt(j))!==-1){ j++; } str = str.substring(j); } ...
自己动手实现符合Promise/A+规范的Promise
Promise异步实现之前在JS异步函数小结里面初步介绍了JS里面的一些异步操作与 Promise 的使用方法,我们要知其然也要知其所以然,所以让我们看一下如何动手实现自己的 MyPromise。
Promise/A+协议协议是实现的基础,Promise/A+协议的中文参考网站如下:
https://www.ituring.com.cn/article/66566
英文网站如下:
https://promisesaplus.com/
实现最简单的构造函数,可以满足回调函数的调用
首先Promise构造参数只能接受函数,否则报错。
Promise内部变量包括:
值 value => 指任何 JavaScript 的合法值(包括 undefined , thenable 和 promise)。
拒因 reason => 值一个 promise 拒绝的原因。
状态 state => promise 执行所处的状态
Promise规范规定了Promise的状态一共有三种:Pending、Fulfilled 及 Rejected。状态之间的转换只能是 Pending =&g ...
D3实现多对多关联关系弧线图
多对多关联关系基于D3实现的多对多关联关系:github地址
各人员之间的互动关系、各公司上下游企业的关联关系、各地之间的交互关系等等,都是多对多关联关系的表达,他们之间可以通过矩阵图的形式来表达, 如下图所示 (用python的heatmap:
而利用 D3库函数可以实现更为酷炫的弧线,如下图所示:
要画多方关系图,首先需要确定绘制的数据,是一个 N * N 的矩阵。
1234567891011121314matrix = [ const matrix = [ [1, 41, 0, 0, 8, 4, 2, 0, 5, 5], [6, 0, 1, 1, 1, 0, 4, 1, 0, 1], [1, 12, 0, 0, 3, 0, 1, 0, 1, 3], [0, 11, 3, 0, 4, 1, 1, 0, 0, 2], [1, 1, 0, 0, 1, 0, 0, 2, 2, 0], [4, 0, 4, 0, 0, 0, 0, 1, 0, 1], [0, 6, 0, 0, ...
JS实现图片的懒加载
场景需求在长博客、商品网站上经常见到大量的图片,而同时加载如此多的图片会导致服务器响应慢、页面卡顿,用户体验不佳。
而图片懒加载就是应对这个痛点。图片懒加载技术就是根据图片在可视区域的位置对图片进行逐步加载,利用 DOM对象元素属性、分流等技术实现。
实现原理步骤一 隐藏懒加载图片的 src 属性我们首先需要确定懒加载的图片资源,对于 img 标签,首先把src 属性用自定义的属性如 data-src 代替,等到图片需要加载时我们将 data-src 的网址赋予 src 属性即可。
1<img data-src='./dzq.jpg' alt="dzq">
步骤二 判断待加载图片是否位于视窗范围内DOM 元素拥有一个方法 element.getBoundingClientRect(),可以获取该元素的大小及其相对于视口的位置,方法返回的是一个 DOMRect 对象,其 left, top, right, bottom 属性解释了相对于视口位置,如下所示。
然后利用 img.getBoundingClientRect(). ...