JS中的设计模式(下)
命令模式命令模式中的命令(command)指的是一个执行某些特定事情的指令。 命令模式最常见的应用场景是:有时候需要向某些对象发送请求,但是并不知道请求的接收者是谁,也不知道被请求的操作是什么。此时希望用一种松耦合的方式来设计程序,使得请求发送者和请求接收者能够消除彼此之间的耦合关系。 例如前端开发分为界面开发以及代码逻辑开发两部分,界面开发的同学设计了一个刷新按钮,点击可以执行刷新操作。 1234<button id="refreshBtn">刷新</button><script>let refreshBth = document.getElementById('refreshBtn');</script> 但是这时候负责开发实际代码逻辑的同学由于业务比较复杂,因此还没来得及开发完成,此时界面开发的同学不知道如何调用实际的刷新操作。 此时可以利用命令模式,统一规定了命令的执行需要调用 execute 方法。 12345let setCommand = function(button, com...
JS中的设计模式(上)
单例模式js 程序中很多情况下只需要创建一个对象,例如全局缓存、widows 对象、线程池、以及界面中具备唯一性的窗口,此时需要利用单例模式来保证对象的唯一性。 使用代理实现 单一职原则 ,将创建单例的 DIV 与管理代理的代码分开。 123456789101112131415161718// 创建 DIV 逻辑CreateDiv = function(html){ this.html = html; this.init();}CreateDiv.prototype.init = function(){ const div = document.createElement('div'); div.innerHtml = this.html; document.body.appendChild(div);}SingletonProxy = (function(){ let instance = null; return function(html){ ...
自己实现 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 = { ...
自己实现 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 ...
自己实现 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 ...



