React 详解

React

React的重点

webpack

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。
当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle
其它相似打包工具还有rollup.js 、 parcel、FIS等
按照webpack的指南**(注意是指南不是概念不是api)**进行针对性的讲解即可,需要被充一下工程化的知识

工程化

这个部分的内容可以做为一些思想给学员讲解,不需要学员掌握。可以理解为扩展的内容

什么是JS项目工程化

  • 版本控制
  • 自动化持续继承、持续交付(CI/CD)
  • 代码质量控制(QA)
  • 工具
  • 模块化
  • 文档
  • demo

编译过程

自动化处理每次push, tag, release的任务队列

  1. 安装

      安装 : npm命令行工具
      安全审计:npm audit
    
  2. Lint

      格式检查: eslint/stylelint
      格式化: prettier
    
  3. 测试

      测试套装: jest / mocha / ava / kamar
      代码覆盖量: nyc / codecov / coveralls
    
  4. 构建

      转换器: babel / TS / flow
      预处理器: sass / less / postcss
      代码混淆: uglify-js / terser
      打包及tree shaking: webpack / rollup / parcel
      压缩(gzip等)
      复制 / 删除 / 移动文件
      检查打包文件的大小
      移除无用的代码
    
  5. push

      交付: git
      发布: npm
    
  6. 部署

     服务器
     Pages: git pages
     云服务器: aliyun / qcloud / aws
    
  7. Story Book

create-react-app

全局安装create-react-app

$ npm install -g create-react-app

创建一个项目

$ create-react-app your-app 注意命名方式
Creating a new React app in /dir/your-app.
Installing packages. This might take a couple of minutes. 安装过程较慢,可以推荐学员使用yarn
Installing react, react-dom, and react-scripts...

如果不想全局安装,可以直接使用npx

$ npx create-react-app your-app 也可以实现相同的效果

这需要等待一段时间,这个过程实际上会安装三个东西

  • react: react的顶级库 react-dom:
  • 因为react有很多的运行环境,比如app端的react-native,我们要在web上运行就使用react-dom
  • react-scripts: 包含运行和打包react应用程序的所有脚本及配置
  • 出现下面的界面,表示创建项目成功:
Success! Created your-app at /dir/your-app
Inside that directory, you can run several commands:
npm start
Starts the development server.
npm run build
Bundles the app into static files for production.
npm test
Starts the test runner.
npm run eject
Removes this tool and copies build dependencies, configuration files
and scripts into the app directory. If you do this, you can’t go back!
We suggest that you begin by typing:
cd your-app
npm start
Happy hacking!

根据上面的提示,通过cd your-app命令进入目录并运行npm start即可运行项目。
生成项目的目录结构如下:

├── README.md             使用方法的文档
├── node_modules          所有的依赖安装的目录
├── package-lock.json     锁定安装时的包的版本号,保证团队的依赖能保证一致。
├── package.json          
├── public                静态公共目录
└── src                   开发用的源代码目录
  • 常见问题: npm安装失败
  • 切换为npm镜像为淘宝镜像
  • 使用yarn,如果本来使用yarn还要失败,还得把yarn的源切换到国内
  • 如果还没有办法解决,请删除node_modules及package-lock.json然后重新执行npm install命令
  • 再不能解决就删除node_modules及package-lock.json的同时清除npm缓存npm cache clean --force之后再执行npm install命令

关于React

React部分的内容包含了所有授课的思路

React的起源和发展

React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。

React与传统MVC的关系

轻量级的视图层库!A JavaScript library for building user interfaces
React不是一个完整的MVC框架,最多可以认为是MVC中的V(View),甚至React并不非常认可MVC开发模式;React 构建页面 UI 的库。可以简单地理解为,React 将将界面分成了各个独立的小块,每一个块就是组件,这些组件之间可以组合、嵌套,就成了我们的页面。

React高性能的体现:虚拟DOM

React高性能的原理:

在Web开发中我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而复杂或频繁的DOM操作通常是性能瓶颈产生的原因(如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标)。
React为此引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A-B,B-A,React会认为A变成B,然后又从B变成A UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。
尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,部而对实际DOM进行操作的仅仅是Diff分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。
React Fiber:

在react 16之后发布的一种react 核心算法,React Fiber是对核心算法的一次重新实现(官网说法)。之前用的是diff算法。
在之前React中,更新过程是同步的,这可能会导致性能问题。
当React决定要加载或者更新组件树时,会做很多事,比如调用各个组件的生命周期函数,计算和比对Virtual DOM,最后更新DOM树,这整个过程是同步进行的,也就是说只要一个加载或者更新过程开始,中途不会中断。因为JavaScript单线程的特点,如果组件树很大的时候,每个同步任务耗时太长,就会出现卡顿。
React Fiber的方法其实很简单——分片。把一个耗时长的任务分成很多小片,每一个小片的运行时间很短,虽然总时间依然很长,但是在每个小片执行完之后,都给其他任务一个执行的机会,这样唯一的线程就不会被独占,其他任务依然有运行的机会。

React的特点和优势

  1. 虚拟DOM
    我们以前操作dom的方式是通过document.getElementById()的方式,这样的过程实际上是先去读取html的dom结构,将结构转换成变量,再进行操作
    而reactjs定义了一套变量形式的dom模型,一切操作和换算直接在变量中,这样减少了操作真实dom,性能真实相当的高,和主流MVC框架有本质的区别,并不和dom打交道
  2. 组件系统
    react最核心的思想是将页面中任何一个区域或者元素都可以看做一个组件 component
    那么什么是组件呢?
    组件指的就是同时包含了html、css、js、image元素的聚合体
    使用react开发的核心就是将页面拆分成若干个组件,并且react一个组件中同时耦合了css、js、image,这种模式整个颠覆了过去的传统的方式
  3. 单向数据流
    其实reactjs的核心内容就是数据绑定,所谓数据绑定指的是只要将一些服务端的数据和前端页面绑定好,开发者只关注实现业务就行了
  4. JSX 语法
    在vue中,我们使用render函数来构建组件的dom结构性能较高,因为省去了查找和编译模板的过程,但是在render中利用createElement创建结构的时候代码可读性较低,较为复杂,此时可以利用jsx语法来在render中创建dom,解决这个问题,但是前提是需要使用工具来编译jsx

编写第一个react应用程序

//react开发需要引入多个依赖文件:react.js、react-dom.js,分别又有开发版本和生产版本,create-react-app里已经帮我们把这些东西都安装好了。把通过CRA创建的工程目录下的src目录清空,然后在里面重新创建一个index.js. 写入以下代码:
// 从 react 的包当中引入了 React。只要你要写 React.js 组件就必须引入React, 因为react里有一种语法叫JSX,稍后会讲到JSX,要写JSX,就必须引入React
import React from 'react'
// ReactDOM 可以帮助我们把 React 组件渲染到页面上去,没有其它的作用了。它是从 react-dom 中引入的,而不是从 react 引入。
import ReactDOM from 'react-dom'
// ReactDOM里有一个render方法,功能就是把组件渲染并且构造 DOM 树,然后插入到页面上某个特定的元素上
ReactDOM.render(
// 这里就比较奇怪了,它并不是一个字符串,看起来像是纯 HTML 代码写在 JavaScript 代码里面。语法错误吗?这并不是合法的 JavaScript 代码, “在 JavaScript 写的标签的”语法叫 JSX- JavaScript XML。
<h1>欢迎进入React的世界</h1>,
// 渲染到哪里
document.getElementById('root')
)

元素与组件

如果代码多了之后,不可能一直在render方法里写,所以就需要把里面的代码提出来,定义一个变量,像这样:

import React from 'react'
import ReactDOM from 'react-dom'
// 这里感觉又不习惯了?这是在用JSX定义一下react元素
const app = <h1>欢迎进入React的世界</h1>
ReactDOM.render(
app,
document.getElementById('root')
)

函数式组件

由于元素没有办法传递参数,所以我们就需要把之前定义的变量改为一个方法,让这个方法去return一个元素:

import React from 'react'
import ReactDOM from 'react-dom'
// 特别注意这里的写法,如果要在JSX里写js表达式(只能是表达式,不能流程控制),就需要加 {},包括注释也是一样,并且可以多层嵌套
const app = (props) => <h1>欢迎进入{props.name}的世界</h1>
ReactDOM.render(
app({
	name: 'react'
}),
document.getElementById('root')
)

这里我们定义的方法实际上也是react定义组件的第一种方式-定义函数式组件,这也是无状态组件。但是这种写法不符合react的jsx的风格,更好的方式是使用以下方式进行改造

import React from 'react'
import ReactDOM from 'react-dom'
const App = (props) => <h1>欢迎进入{props.name}的世界</h1>
ReactDOM.render(
// React组件的调用方式
<App name="react" />,
document.getElementById('root')
)

这样一个完整的函数式组件就定义好了。但要注意!注意!注意!组件名必须大写,否则报错。

class组件

ES6的加入让JavaScript直接支持使用class来定义一个类,react的第二种创建组件的方式就是使用的类的继承,ES6 class是目前官方推荐的使用方式,它使用了ES6标准语法来构建,看以下代码:

import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
	return (
		// 注意这里得用this.props.name, 必须用this.props
		<h1>欢迎进入{this.props.name}的世界</h1>
	  )
	}
}
ReactDOM.render(
<App name="react" />,document.getElementById('root'))

运行结果和之前完全一样,因为JS里没有真正的class,这个class只是一个语法糖, 但二者的运行机制底层运行机制不一样。

  • 函数式组件是直接调用, 在前面的代码里已经有看到
  • es6 class组件其实就是一个构造器,每次使用组件都相当于在实例化组件,像这样:
import React from 'react'
import ReactDOM from 'react-dom'
class App extends React.Component {
render () {
return (
    <h1>欢迎进入{this.props.name}的世界</h1>
  )
}
}
const app = new App({name: 'react'}).render()
	ReactDOM.render(
		app,
	document.getElementById('root')
)

更老的一种方法

在16以前的版本还支持这样创建组件, 但现在的项目基本上不用

React.createClass({
render () {
return (
		<div>{this.props.xxx}</div>
	  )
	}
})

组件的组合、嵌套

将一个组件渲染到某一个节点里的时候,会将这个节点里原有内容覆盖
组件嵌套的方式就是将子组件写入到父组件的模板中去,且react没有Vue中的内容分发机制(slot),所以我们在一个组件的模板中只能看到父子关系

// 从 react 的包当中引入了 React 和 React.js 的组件父类 Component
// 还引入了一个React.js里的一种特殊的组件 Fragment
import React, { Component, Fragment } from 'react'
import ReactDOM from 'react-dom'
class Title extends Component {
	render () {
		return (
			<h1>欢迎进入React的世界</h1>
		  )
		}
	}
	class Content extends Component {
		render () {
			return (
				<p>React.js是一个构建UI的库</p>
			 )
		}
	}
	/** 由于每个React组件只能有一个根节点,所以要渲染多个组件的时候,需要在最外层包一个容器,如果使用div, 会生成多余的一层dom
	
	class App extends Component {
		render () {
			return (
				  
<Content /> </div> ) } } **/</span> <span class="token comment">// 如果不想生成多余的一层dom可以使用React提供的Fragment组件在最外层进行包裹</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Fragment<span class="token operator">></span> <span class="token operator"><</span>Title <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Content <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Fragment<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <h2>JSX 原理</h2> <p>要明白JSX的原理,需要先明白如何用 JavaScript 对象来表现一个 DOM 元素的结构?<br> 看下面的DOM结构</p> <pre><code class="prism language-javascript"><span class="token operator"><</span>div <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">'app'</span> id<span class="token operator">=</span><span class="token string">'appRoot'</span><span class="token operator">></span> <span class="token operator"><</span>h1 <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">'title'</span><span class="token operator">></span>欢迎进入React的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span> React<span class="token punctuation">.</span>js 是一个帮助你构建页面 <span class="token constant">UI</span> 的库 <span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> </code></pre> <p>上面这个 HTML 所有的信息我们都可以用 JavaScript 对象来表示:</p> <pre><code class="prism language-javascript"><span class="token punctuation">{</span> tag<span class="token operator">:</span> <span class="token string">'div'</span><span class="token punctuation">,</span> attrs<span class="token operator">:</span> <span class="token punctuation">{</span> className<span class="token operator">:</span> <span class="token string">'app'</span><span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token string">'appRoot'</span><span class="token punctuation">}</span><span class="token punctuation">,</span> children<span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> tag<span class="token operator">:</span> <span class="token string">'h1'</span><span class="token punctuation">,</span> attrs<span class="token operator">:</span> <span class="token punctuation">{</span> className<span class="token operator">:</span> <span class="token string">'title'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> children<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'欢迎进入React的世界'</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> tag<span class="token operator">:</span> <span class="token string">'p'</span><span class="token punctuation">,</span> attrs<span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span> children<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'React.js 是一个构建页面 UI 的库'</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> </code></pre> <p>但是用 JavaScript 写起来太长了,结构看起来又不清晰,用 HTML 的方式写起来就方便很多了。<br> 于是 React.js 就把 JavaScript 的语法扩展了一下,让 JavaScript 语言能够支持这种直接在 JavaScript 代码里面编写类似 HTML 标签结构的语法,这样写起来就方便很多了。编译的过程会把类似 HTML 的 JSX 结构转换成 JavaScript 的对象结构。<br> 下面代码:</p> <p>i</p> <pre><code class="prism language-javascript">mport React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div className<span class="token operator">=</span><span class="token string">'app'</span> id<span class="token operator">=</span><span class="token string">'appRoot'</span><span class="token operator">></span> <span class="token operator"><</span>h1 className<span class="token operator">=</span><span class="token string">'title'</span><span class="token operator">></span>欢迎进入React的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span> React<span class="token punctuation">.</span>js 是一个构建页面 <span class="token constant">UI</span> 的库 <span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App <span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> </code></pre> <p>编译之后将得到这样的代码:</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span> <span class="token string">"div"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> className<span class="token operator">:</span> <span class="token string">'app'</span><span class="token punctuation">,</span> id<span class="token operator">:</span> <span class="token string">'appRoot'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span> <span class="token string">"h1"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> className<span class="token operator">:</span> <span class="token string">'title'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">"欢迎进入React的世界"</span> <span class="token punctuation">)</span><span class="token punctuation">,</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span> <span class="token string">"p"</span><span class="token punctuation">,</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token string">"React.js 是一个构建页面 UI 的库"</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span>App<span class="token punctuation">)</span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <p>React.createElement 会构建一个 JavaScript 对象来描述你 HTML 结构的信息,包括标签名、属性、还有子元素等, 语法为</p> <pre><code class="prism language-javascript">React<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span> type<span class="token punctuation">,</span> <span class="token punctuation">[</span>props<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token operator">...</span>children<span class="token punctuation">]</span> <span class="token punctuation">)</span> </code></pre> <p>所谓的 JSX 其实就是 JavaScript 对象,所以使用 React 和 JSX 的时候一定要经过编译的过程:</p> <pre><code>JSX —使用react构造组件,bable进行编译—> JavaScript对象 — ReactDOM.render()—>DOM元素 —>插入页面 #组件中DOM样式 </code></pre> <ul> <li>行内样式</li> <li>想给虚拟dom添加行内样式,需要使用表达式传入样式对象的方式来实现:</li> </ul> <pre><code class="prism language-javascript"><span class="token comment">// 注意这里的两个括号,第一个表示我们在要JSX里插入JS了,第二个是对象的括号</span> <span class="token operator"><</span>p style<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>color<span class="token operator">:</span><span class="token string">'red'</span><span class="token punctuation">,</span> fontSize<span class="token operator">:</span><span class="token string">'14px'</span><span class="token punctuation">}</span><span class="token punctuation">}</span><span class="token operator">></span>Hello world<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> </code></pre> <p>行内样式需要写入一个样式对象,而这个样式对象的位置可以放在很多地方,例如render函数里、组件原型上、外链js文件中</p> <ul> <li>使用class</li> <li>React推荐我们使用行内样式,因为React觉得每一个组件都是一个独立的整体<br> 其实我们大多数情况下还是大量的在为元素添加类名,但是需要注意的是,class需要写成className(因为毕竟是在写类js代码,会收到js规则的现在,而class是关键字)</li> </ul> <pre><code class="prism language-javascript"><span class="token operator"><</span>p className<span class="token operator">=</span><span class="token string">"hello"</span> style <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>style<span class="token punctuation">}</span><span class="token operator">></span>Hello world<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> </code></pre> <ul> <li> <p>不同的条件添加不同的样式<br> 有时候需要根据不同的条件添加不同的样式,比如:完成状态,完成是绿色,未完成是红色。那么这种情况下,我们推荐使用classnames这个包:</p> </li> <li> <p>css-in-js<br> styled-components是针对React写的一套css-in-js框架,简单来讲就是在js中写css。npm链接<br> #TodoList 组件化开发React todolist, 项目开发中的组件的基本目录结构基本上是这样的:</p> </li> </ul> <pre><code>/your-project src … components YourComponentOne index.js/YourComponentOne.js YourComponentTwo index.js/YourComponentTwo.js index.js 用于导出组件 注意:一个组件只干一件事情 ,所以TodoList和TodoItem要做成两个组件,这样也方便于后期理解shouldComponentUpdate </code></pre> <h2>组件的数据挂载方式</h2> <h3>属性(props)</h3> <p>props是正常是外部传入的,组件内部也可以通过一些方式来初始化的设置,属性不能被组件自己更改,但是你可以通过父组件主动重新渲染的方式来传入新的 props<br> 属性是描述性质、特点的,组件自己不能随意更改。<br> 之前的组件代码里面有props的简单使用,总的来说,在使用一个组件的时候,可以把参数放在标签的属性当中,所有的属性都会作为组件 props 对象的键值。通过箭头函数创建的组件,需要通过函数的参数来接收<br> props:</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> Fragment <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">Title</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>h1<span class="token operator">></span>欢迎进入<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>name<span class="token punctuation">}</span>的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">Content</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>p<span class="token operator">></span><span class="token punctuation">{</span>props<span class="token punctuation">.</span>name<span class="token punctuation">}</span>是一个构建<span class="token constant">UI</span>的库<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Fragment<span class="token operator">></span> <span class="token operator"><</span>Title name<span class="token operator">=</span><span class="token string">"React"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Content name<span class="token operator">=</span><span class="token string">"React.js"</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Fragment<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <h3>设置组件的默认props</h3> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> Fragment <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">Title</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token comment">// 使用类创建的组件,直接在这里写static方法,创建defaultProps</span> <span class="token keyword">static</span> defaultProps <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'React'</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>h1<span class="token operator">></span>欢迎进入<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>name<span class="token punctuation">}</span>的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">Content</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>p<span class="token operator">></span><span class="token punctuation">{</span>props<span class="token punctuation">.</span>name<span class="token punctuation">}</span>是一个构建<span class="token constant">UI</span>的库<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 使用箭头函数创建的组件,需要在这个组件上直接写defaultProps属性</span> Content<span class="token punctuation">.</span>defaultProps <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'React.js'</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Fragment<span class="token operator">></span> <span class="token punctuation">{</span><span class="token comment">/* 由于设置了defaultProps, 不传props也能正常运行,如果传递了就会覆盖defaultProps的值 */</span><span class="token punctuation">}</span> <span class="token operator"><</span>Title <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Content <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Fragment<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <h3>props.children</h3> <p>我们知道使用组件的时候,可以嵌套。要在自定义组件的使用嵌套结构,就需要使用 props.children 。在实际的工作当中,我们几乎每天都需要用这种方式来编写组件。</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> Fragment <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">Title</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>h1<span class="token operator">></span>欢迎进入<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>children<span class="token punctuation">}</span>的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> <span class="token function-variable function">Content</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>p<span class="token operator">></span><span class="token punctuation">{</span>props<span class="token punctuation">.</span>children<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Fragment<span class="token operator">></span> <span class="token operator"><</span>Title<span class="token operator">></span>React<span class="token operator"><</span><span class="token operator">/</span>Title<span class="token operator">></span> <span class="token operator"><</span>Content<span class="token operator">></span><span class="token operator"><</span>i<span class="token operator">></span>React<span class="token punctuation">.</span>js<span class="token operator"><</span><span class="token operator">/</span>i<span class="token operator">></span>是一个构建<span class="token constant">UI</span>的库<span class="token operator"><</span><span class="token operator">/</span>Content<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Fragment<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <p><strong>使用prop-types检查props</strong></p> <p>React其实是为了构建大型应用程序而生, 在一个大型应用中,根本不知道别人使用你写的组件的时候会传入什么样的参数,有可能会造成应用程序运行不了,但是不报错。为了解决这个问题,React提供了一种机制,让写组件的人可以给组件的props设定参数检查,需要安装和使用prop-types:</p> <h4>定义state</h4> <p>第一种方式</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'React'</span><span class="token punctuation">,</span> isLiked<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>欢迎来到<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>name<span class="token punctuation">}</span>的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>button<span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked <span class="token operator">?</span> <span class="token string">'❤️取消'</span> <span class="token operator">:</span> <span class="token string">'?收藏'</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <p>另一种方式(推荐)</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'React'</span><span class="token punctuation">,</span> isLiked<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>欢迎来到<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>name<span class="token punctuation">}</span>的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>button<span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked <span class="token operator">?</span> <span class="token string">'❤️取消'</span> <span class="token operator">:</span> <span class="token string">'?收藏'</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <p>this.props和this.state是纯js对象,在vue中,data属性是利用Object.defineProperty处理过的,更改​data的数据的时候会触发数据的getter和setter,但是React中没有做这样的处理,如果直接更改的话,react是无法得知的,所以,需要使用特殊的更改状态的方法setState。<br> ###setState<br> isLiked 存放在实例的 state 对象当中,组件的 render 函数内,会根据组件的 state 的中的isLiked不同显示“取消”或“收藏”内容。下面给 button 加上了点击的事件监听。</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'React'</span><span class="token punctuation">,</span> isLiked<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function-variable function">handleBtnClick</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> isLiked<span class="token operator">:</span> <span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>欢迎来到<span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>name<span class="token punctuation">}</span>的世界<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleBtnClick<span class="token punctuation">}</span><span class="token operator">></span> <span class="token punctuation">{</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">在这里插入代码片</span><span class="token template-punctuation string">`</span></span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked <span class="token operator">?</span> <span class="token string">'❤️取消'</span> <span class="token operator">:</span> <span class="token string">'?收藏'</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <p>setState有两个参数<br> 第一个参数可以是对象,也可以是方法return一个对象,我们把这个参数叫做updater</p> <ul> <li>参数是对象</li> </ul> <pre><code class="prism language-javascript"><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> isLiked<span class="token operator">:</span> <span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked <span class="token punctuation">}</span><span class="token punctuation">)</span> </code></pre> <ul> <li>参数是方法</li> </ul> <pre><code class="prism language-javascript"><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">prevState<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> isLiked<span class="token operator">:</span> <span class="token operator">!</span>prevState<span class="token punctuation">.</span>isLiked <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> </code></pre> <p>注意的是这个方法接收两个参数,第一个是上一次的state, 第二个是props<br> setState是异步的,所以想要获取到最新的state,没有办法获取,就有了第二个参数,这是一个可选的回调函数</p> <pre><code class="prism language-javascript"><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">prevState<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> isLiked<span class="token operator">:</span> <span class="token operator">!</span>prevState<span class="token punctuation">.</span>isLiked <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'回调里的'</span><span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'setState外部的'</span><span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>isLiked<span class="token punctuation">)</span> </code></pre> <p><strong>属性vs状态</strong><br> 相似点:都是纯js对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)<br> 不同点:</p> <ol> <li>属性能从父组件获取,状态不能</li> <li>属性可以由父组件修改,状态不能</li> <li>属性能在内部设置默认值,状态也可以</li> <li>属性不在组件内部修改,状态要改</li> <li>属性能设置子组件初始值,状态不可以</li> <li>属性可以修改子组件的值,状态不可以<br> state 的主要作用是用于组件保存、控制、修改自己的可变状态。state 在组件内部初始化,可以被组件自身修改,而外部不能访问也 不能修改。你可以认为 state 是一个局部的、只能被组件自身控制的数据源。state 中状态可以通过 this.setState方法进行更新,setState 会导致组件的重新渲染。<br> props 的主要作用是让使用该组件的父组件可以传入参数来配置该组件。它是外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的 props,否则组件的 props 永远保持不变。<br> 如果搞不清 state 和 props 的使用场景,记住一个简单的规则:尽量少地用 state,多用 props。<br> 没有 state 的组件叫无状态组件(stateless component),设置了 state 的叫做有状态组件(stateful component)。因为状态会带来管理的复杂性,我们尽量多地写无状态组件,尽量少地写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。<br> 如果有多个组件共享一个数据,把这个数据放到共同的父级组件中来管理</li> </ol> <p><strong>受控组件与非受控组件</strong></p> <p>React组件的数据渲染是否被调用者传递的props完全控制,控制则为受控组件,否则非受控组件</p> <h2>渲染数据</h2> <ul> <li>条件渲染</li> </ul> <pre><code class="prism language-javascript"><span class="token punctuation">{</span> condition <span class="token operator">?</span> <span class="token string">'❤️取消'</span> <span class="token operator">:</span> <span class="token string">'?收藏'</span> <span class="token punctuation">}</span> </code></pre> <ul> <li>列表渲染</li> </ul> <pre><code class="prism language-javascript"><span class="token comment">// 数据</span> <span class="token keyword">const</span> people <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> name<span class="token operator">:</span> <span class="token string">'Leo'</span><span class="token punctuation">,</span> age<span class="token operator">:</span> <span class="token number">35</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> id<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> name<span class="token operator">:</span> <span class="token string">'XiaoMing'</span><span class="token punctuation">,</span> age<span class="token operator">:</span> <span class="token number">16</span> <span class="token punctuation">}</span><span class="token punctuation">]</span> <span class="token comment">// 渲染列表</span> <span class="token punctuation">{</span> people<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">person</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>dl key<span class="token operator">=</span><span class="token punctuation">{</span>person<span class="token punctuation">.</span>id<span class="token punctuation">}</span><span class="token operator">></span> <span class="token operator"><</span>dt<span class="token operator">></span><span class="token punctuation">{</span>person<span class="token punctuation">.</span>name<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>dt<span class="token operator">></span> <span class="token operator"><</span>dd<span class="token operator">></span>age<span class="token operator">:</span> <span class="token punctuation">{</span>person<span class="token punctuation">.</span>age<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>dd<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>dl<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <p>React的高效依赖于所谓的 Virtual-DOM,尽量不碰 DOM。对于列表元素来说会有一个问题:元素可能会在一个列表中改变位置。要实现这个操作,只需要交换一下 DOM 位置就行了,但是React并不知道其实我们只是改变了元素的位置,所以它会重新渲染后面两个元素(再执行 Virtual-DOM ),这样会大大增加 DOM 操作。但如果给每个元素加上唯一的标识,React 就可以知道这两个元素只是交换了位置,这个标识就是key,这个 key 必须是每个元素唯一的标识</p> <ul> <li>dangerouslySetHTML<br> 对于富文本创建的内容,后台拿到的数据是这样的:</li> </ul> <pre><code class="prism language-javascript">content <span class="token operator">=</span> <span class="token string">"<p>React.js是一个构建UI的库</p>"</span> </code></pre> <p>处于安全的原因,React当中所有表达式的内容会被转义,如果直接输入,标签会被当成文本。这时候就需要使用dangerouslySetHTML属性,它允许我们动态设置innerHTML</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> content <span class="token operator">:</span> <span class="token string">"<p>React.js是一个构建UI的库</p>"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div <span class="token comment">// 注意这里是两个下下划线 __html</span> dangerouslySetInnerHTML<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span>__html<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>content<span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <h4>事件处理</h4> <p><strong>绑定事件</strong></p> <p>采用on+事件名的方式来绑定一个事件,注意,这里和原生的事件是有区别的,原生的事件全是小写onclick, React里的事件是驼峰onClick,React的事件并不是原生事件,而是合成事件。</p> <p><strong>事件handler的写法</strong></p> <ul> <li>直接在render里写行内的箭头函数(不推荐)</li> <li>在组件内使用箭头函数定义一个方法(推荐)</li> <li>直接在组件内定义一个非箭头函数的方法,然后在render里直接使用onClick={this.handleClick.bind(this)}(不推荐)</li> <li>直接在组件内定义一个非箭头函数的方法,然后在constructor里bind(this)(推荐)</li> </ul> <h4>Event 对象</h4> <p>和普通浏览器一样,事件handler会被自动传入一个 event 对象,这个对象和普通的浏览器 event 对象所包含的方法和属性都基本一致。不同的是 React中的 event 对象并不是浏览器提供的,而是它自己内部所构建的。它同样具有event.stopPropagation、event.preventDefault 这种常用的方法</p> <p><strong>事件的参数传递</strong></p> <ul> <li>在render里调用方法的地方外面包一层箭头函数</li> <li>在render里通过this.handleEvent.bind(this, 参数)这样的方式来传递</li> <li>通过event传递</li> <li>比较推荐的是做一个子组件, 在父组件中定义方法,通过props传递到子组件中,然后在子组件件通过this.props.method来调用</li> </ul> <h3>处理用户输入</h3> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> xing<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span> ming<span class="token operator">:</span> <span class="token string">''</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function-variable function">handleInputChange</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token punctuation">[</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>name<span class="token punctuation">]</span><span class="token operator">:</span> e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>value <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> xing<span class="token punctuation">,</span> ming <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>label<span class="token operator">></span> <span class="token operator"><</span>span<span class="token operator">></span>姓<span class="token operator">:</span><span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> name<span class="token operator">=</span><span class="token string">"xing"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>xing<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleInputChange<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>label<span class="token operator">></span> <span class="token operator"><</span>label<span class="token operator">></span> <span class="token operator"><</span>span<span class="token operator">></span>名<span class="token operator">:</span><span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> name<span class="token operator">=</span><span class="token string">"ming"</span> value<span class="token operator">=</span><span class="token punctuation">{</span>ming<span class="token punctuation">}</span> onChange<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>handleInputChange<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>label<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span>欢迎您<span class="token operator">:</span> <span class="token punctuation">{</span>xing<span class="token punctuation">}</span><span class="token punctuation">{</span>ming<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <h2>组件的生命周期</h2> <p>React中组件也有生命周期,也就是说也有很多钩子函数供我们使用, 组件的生命周期,我们会分为四个阶段,初始化、运行中、销毁、错误处理(16.3之后)</p> <h3>初始化</h3> <p>在组件初始化阶段会执行</p> <ul> <li>constructor</li> <li>static getDerivedStateFromProps()</li> <li>componentWillMount() / UNSAFE_componentWillMount()</li> <li>render()</li> <li>componentDidMount()</li> </ul> <h3>更新阶段</h3> <p>props或state的改变可能会引起组件的更新,组件重新渲染的过程中会调用以下方法:</p> <ol> <li>componentWillReceiveProps() / UNSAFE_componentWillReceiveProps()</li> <li>static getDerivedStateFromProps()</li> <li>shouldComponentUpdate()</li> <li>componentWillUpdate() / UNSAFE_componentWillUpdate()</li> <li>render()</li> <li>getSnapshotBeforeUpdate()</li> <li>componentDidUpdate()</li> </ol> <h3>卸载阶段</h3> <ol> <li>componentWillUnmount()</li> </ol> <h3>错误处理</h3> <ol> <li>componentDidCatch()</li> </ol> <h3>各生命周期详解</h3> <p><strong>1. constructor(props)</strong></p> <p>React组件的构造函数在挂载之前被调用。在实现React.Component构造函数时,需要先在添加其他内容前,调用super(props),用来将父组件传来的props绑定到这个类中,使用this.props将会得到。<br> 官方建议不要在constructor引入任何具有副作用和订阅功能的代码,这些应当使用componentDidMount()。<br> constructor中应当做些初始化的动作,如:初始化state,将事件处理函数绑定到类实例上,但也不要使用setState()。如果没有必要初始化state或绑定方法,则不需要构造constructor,或者把这个组件换成纯函数写法。<br> 当然也可以利用props初始化state,在之后修改state不会对props造成任何修改,但仍然建议大家提升状态到父组件中,或使用redux统一进行状态管理。</p> <pre><code class="prism language-javascript"><span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span>props<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> isLiked<span class="token operator">:</span> props<span class="token punctuation">.</span>isLiked <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p><strong>2.static getDerivedStateFromProps(nextProps, prevState)</strong></p> <p>getDerivedStateFromProps 是react16.3之后新增,在组件实例化后,和接受新的props后被调用。他必须返回一个对象来更新状态,或者返回null表示新的props不需要任何state的更新。<br> 如果是由于父组件的props更改,所带来的重新渲染,也会触发此方法。<br> 调用steState()不会触发getDerivedStateFromProps()。<br> 之前这里都是使用constructor+componentWillRecieveProps完成相同的功能的<br> <strong>3. componentWillMount() / UNSAFE_componentWillMount()</strong></p> <p>componentWillMount()将在React未来版本(官方说法 17.0)中被弃用。UNSAFE_componentWillMount()在组件挂载前被调用,在这个方法中调用setState()不会起作用,是由于他在render()前被调用。<br> 为了避免副作用和其他的订阅,官方都建议使用componentDidMount()代替。这个方法是用于在服务器渲染上的唯一方法。这个方法因为是在渲染之前被调用,也是惟一一个可以直接同步修改state的地方。<br> <strong>4.render()</strong></p> <p>render()方法是必需的。当他被调用时,他将计算this.props和this.state,并返回以下一种类型:</p> <ol> <li>React元素。通过jsx创建,既可以是dom元素,也可以是用户自定义的组件。</li> <li>字符串或数字。他们将会以文本节点形式渲染到dom中。</li> <li>Portals。react 16版本中提出的新的解决方案,可以使组件脱离父组件层级直接挂载在DOM树的任何位置。</li> <li>null,什么也不渲染</li> <li>布尔值。也是什么都不渲染。</li> <li>当返回null,false,ReactDOM.findDOMNode(this)将会返回null,什么都不会渲染。</li> <li>render()方法必须是一个纯函数,他不应该改变state,也不能直接和浏览器进行交互,应该将事件放在其他生命周期函数中。</li> <li>如果shouldComponentUpdate()返回false,render()不会被调用。</li> </ol> <p><strong>5. componentDidMount</strong></p> <p>componentDidMount在组件被装配后立即调用。初始化使得DOM节点应该进行到这里。</p> <p><strong>通常在这里进行ajax请求</strong></p> <p>如果要初始化第三方的dom库,也在这里进行初始化。只有到这里才能获取到真实的dom.</p> <p><strong>6.componentWillReceiveProps()/UNSAFE_componentWillReceiveProps(nextProps)</strong></p> <p>官方建议使用getDerivedStateFromProps函数代替componentWillReceiveProps。当组件挂载后,接收到新的props后会被调用。如果需要更新state来响应props的更改,则可以进行this.props和nextProps的比较,并在此方法中使用this.setState()。<br> 如果父组件会让这个组件重新渲染,即使props没有改变,也会调用这个方法。<br> React不会在组件初始化props时调用这个方法。调用this.setState也不会触发。</p> <p><strong>7.shouldComponentUpdate(nextProps, nextState)</strong><br> 调用shouldComponentUpdate使React知道,组件的输出是否受state和props的影响。默认每个状态的更改都会重新渲染,大多数情况下应该保持这个默认行为。<br> 在渲染新的props或state前,shouldComponentUpdate会被调用。默认为true。这个方法不会在初始化时被调用,也不会在forceUpdate()时被调用。返回false不会阻止子组件在state更改时重新渲染。<br> 如果shouldComponentUpdate()返回false,componentWillUpdate,render和componentDidUpdate不会被调用。</p> <pre><code>官方并不建议在shouldComponentUpdate()中进行深度查询或使用JSON.stringify(),他效率非常低,并且损伤性能。 </code></pre> <p><strong>8.UNSAFE_componentWillUpdate(nextProps, nextState)</strong></p> <p>在渲染新的state或props时,UNSAFE_componentWillUpdate会被调用,将此作为在更新发生之前进行准备的机会。这个方法不会在初始化时被调用。<br> 不能在这里使用this.setState(),也不能做会触发视图更新的操作。如果需要更新state或props,调用getDerivedStateFromProps。</p> <p><strong>9.getSnapshotBeforeUpdate()</strong></p> <p>在react render()后的输出被渲染到DOM之前被调用。它使您的组件能够在它们被潜在更改之前捕获当前值(如滚动位置)。这个生命周期返回的任何值都将作为参数传递给componentDidUpdate()。</p> <p><strong>10.componentDidUpdate(prevProps, prevState, snapshot)</strong></p> <p>在更新发生后立即调用componentDidUpdate()。此方法不用于初始渲染。当组件更新时,将此作为一个机会来操作DOM。只要您将当前的props与以前的props进行比较(例如,如果props没有改变,则可能不需要网络请求),这也是做网络请求的好地方。<br> 如果组件实现getSnapshotBeforeUpdate()生命周期,则它返回的值将作为第三个“快照”参数传递给componentDidUpdate()。否则,这个参数是undefined。</p> <p><strong>11.componentWillUnmount()</strong></p> <p>在组件被卸载并销毁之前立即被调用。在此方法中执行任何必要的清理,例如使定时器无效,取消网络请求或清理在componentDidMount中创建的任何监听。<br> <strong>12.componentDidCatch(error, info)</strong></p> <p>错误边界是React组件,可以在其子组件树中的任何位置捕获JavaScript错误,记录这些错误并显示回退UI,而不是崩溃的组件树。错误边界在渲染期间,生命周期方法以及整个树下的构造函数中捕获错误。<br> 如果类组件定义了此生命周期方法,则它将成错误边界。在它中调用setState()可以让你在下面的树中捕获未处理的JavaScript错误,并显示一个后备UI。只能使用错误边界从意外异常中恢复; 不要试图将它们用于控制流程。<br> 错误边界只会捕获树中下面组件中的错误。错误边界本身不能捕获错误。</p> <h4>PureComponent</h4> <p>PureComponnet里如果接收到的新属性或者是更改后的状态和原属性、原状态相同的话,就不会去重新render了<br> 在里面也可以使用shouldComponentUpdate,而且。是否重新渲染以shouldComponentUpdate的返回值为最终的决定因素。</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> PureComponent <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">class</span> <span class="token class-name">YourComponent</span> <span class="token keyword">extends</span> <span class="token class-name">PureComponent</span> <span class="token punctuation">{</span> …… <span class="token punctuation">}</span> </code></pre> <h4>ref</h4> <p>React提供的这个ref属性,表示为对组件真正实例的引用,其实就是ReactDOM.render()返回的组件实例,ref可以挂载到组件上也可以是dom元素上。</p> <ul> <li>挂到组件(class声明的组件)上的ref表示对组件实例的引用。不能在函数式组件上使用 ref 属性,因为它们没有实例:</li> <li>挂载到dom元素上时表示具体的dom元素节点。</li> <li>在React 最新的版本中,要使用ref, 需要使用React.createRef方法先生成一个ref。</li> </ul> <pre><code class="prism language-javascript"><span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> createRef <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">'react-dom'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 创建inputRef</span> <span class="token keyword">this</span><span class="token punctuation">.</span>inputRef<span class="token operator">=</span><span class="token function">createRef</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">componentDidMount</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>inputRef<span class="token punctuation">.</span>current<span class="token punctuation">)</span> <span class="token comment">// <input type="text"></span> <span class="token punctuation">}</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token punctuation">{</span><span class="token comment">/* 关联ref和dom */</span><span class="token punctuation">}</span> <span class="token operator"><</span>input type<span class="token operator">=</span><span class="token string">"text"</span> ref<span class="token operator">=</span><span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>inputRef<span class="token punctuation">}</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span> <span class="token operator"><</span>App<span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'root'</span><span class="token punctuation">)</span> <span class="token punctuation">)</span> </code></pre> <h3>React Hooks</h3> <p>React Hooks 是 React 16.7.0-alpha 版本推出的新特性, 有了React Hooks,在 react 函数组件中,也可以使用类组件(classes components)的 state 和 组件生命周期。通过下面几个例子来学习React Hooks。</p> <ul> <li>State Hook</li> </ul> <pre><code class="prism language-javascript"><span class="token comment">// useState是react包提供的一个方法</span> <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">"react-dom"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">Counter</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// useState 这个方法可以为我们的函数组件拥有自己的state,它接收一个用于初始 state 的值,返回一对变量。这里我们把计数器的初始值设置为0, 方法都是以set开始</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>count<span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span>你点击了<span class="token punctuation">{</span>count<span class="token punctuation">}</span>次<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setCount</span><span class="token punctuation">(</span>count <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token operator">></span>点击<span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> rootElement <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"root"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token operator"><</span>Counter <span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> rootElement<span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <ul> <li>Effect Hook</li> </ul> <pre><code class="prism language-javascript"><span class="token comment">// useState是react包提供的一个方法</span> <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> useState<span class="token punctuation">,</span> useEffect <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">"react"</span><span class="token punctuation">;</span> <span class="token keyword">import</span> ReactDOM <span class="token keyword">from</span> <span class="token string">"react-dom"</span><span class="token punctuation">;</span> <span class="token keyword">const</span> <span class="token function-variable function">Counter</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// useState 这个方法可以为我们的函数组件拥有自己的state,它接收一个用于初始 state 的值,返回一对变量。这里我们把计数器的初始值设置为0, 方法都是以set开始</span> <span class="token keyword">const</span> <span class="token punctuation">[</span>count<span class="token punctuation">,</span> setCount<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">useState</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 类似于componentDidMount或者componentDidUpdate:</span> <span class="token function">useEffect</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// 更改网页的标题,还可以做其它的监听</span> document<span class="token punctuation">.</span>title <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">你点击了</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>count<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">次</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span>你点击了<span class="token punctuation">{</span>count<span class="token punctuation">}</span>次<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">setCount</span><span class="token punctuation">(</span>count <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">}</span><span class="token operator">></span>点击<span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">const</span> rootElement <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"root"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> ReactDOM<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token operator"><</span>Counter <span class="token operator">/</span><span class="token operator">></span><span class="token punctuation">,</span> rootElement<span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> <ul> <li>React Hooks 的规则</li> <li>只能在顶层调用Hooks。不要在循环,条件或嵌套函数中调用Hook。</li> <li>不要从常规JavaScript函数中调用Hook。只在React函数式组件调用Hooks。</li> <li>自定义hooks可以选择讲解 react</li> <li>内置hooks api</li> <li>Basic Hooks</li> <li>useState</li> <li>useEffect</li> <li>useContext</li> <li>Additiona Hooks</li> <li>useReducer</li> <li>useCallback</li> <li>useMemo</li> <li>useRef</li> <li>useImperativeHandle</li> <li>useLayoutEffect</li> <li>useDebugValue</li> </ul> <h2>组件通信</h2> <p><strong>父组件与子组件通信</strong></p> <ul> <li>父组件将自己的状态传递给子组件,子组件当做属性来接收,当父组件更改自己状态的时候,子组件接收到的属性就会发生改变</li> <li>父组件利用ref对子组件做标记,通过调用子组件的方法以更改子组件的状态,也可以调用子组件的方法… 子组件与父组件通信</li> <li>父组件将自己的某个方法传递给子组件,在方法里可以做任意操作,比如可以更改状态,子组件通过this.props接收到父组件的方法后调用。</li> <li>跨组件通信<br> 在react没有类似vue中的事件总线来解决这个问题,我们只能借助它们共同的父级组件来实现,将非父子关系装换成多维度的父子关系。react提供了context<br> api来实现跨组件通信, React 16.3之后的contextapi较之前的好用。 实例,使用context 实现购物车中的加减功能</li> </ul> <pre><code class="prism language-javascript"><span class="token comment">// counterContext.js</span> <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> createContext <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> Provider<span class="token punctuation">,</span> Consumer<span class="token operator">:</span> CountConsumer <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token function">createContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">class</span> <span class="token class-name">CountProvider</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">constructor</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state <span class="token operator">=</span> <span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token function-variable function">increaseCount</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count <span class="token operator">+</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function-variable function">decreaseCount</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setState</span><span class="token punctuation">(</span><span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count <span class="token operator">-</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Provider value<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>state<span class="token punctuation">.</span>count<span class="token punctuation">,</span> increaseCount<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>increaseCount<span class="token punctuation">,</span> decreaseCount<span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>decreaseCount <span class="token punctuation">}</span><span class="token punctuation">}</span> <span class="token operator">></span> <span class="token punctuation">{</span><span class="token keyword">this</span><span class="token punctuation">.</span>props<span class="token punctuation">.</span>children<span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>Provider<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token punctuation">{</span> CountProvider<span class="token punctuation">,</span> CountConsumer <span class="token punctuation">}</span> </code></pre> <pre><code class="prism language-javascript"><span class="token comment">// 定义CountButton组件</span> <span class="token keyword">const</span> <span class="token function-variable function">CountButton</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>CountConsumer<span class="token operator">></span> <span class="token comment">// consumer的children必须是一个方法</span> <span class="token punctuation">{</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> increaseCount<span class="token punctuation">,</span> decreaseCount <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token punctuation">{</span> type <span class="token punctuation">}</span> <span class="token operator">=</span> props <span class="token keyword">const</span> handleClick <span class="token operator">=</span> type <span class="token operator">===</span> <span class="token string">'increase'</span> <span class="token operator">?</span> increaseCount <span class="token operator">:</span> decreaseCount <span class="token keyword">const</span> btnText <span class="token operator">=</span> type <span class="token operator">===</span> <span class="token string">'increase'</span> <span class="token operator">?</span> <span class="token string">'+'</span> <span class="token operator">:</span> <span class="token string">'-'</span> <span class="token keyword">return</span> <span class="token operator"><</span>button onClick<span class="token operator">=</span><span class="token punctuation">{</span>handleClick<span class="token punctuation">}</span><span class="token operator">></span><span class="token punctuation">{</span>btnText<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>button<span class="token operator">></span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>CountConsumer<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <pre><code class="prism language-javascript"><span class="token comment">// 定义count组件,用于显示数量</span> <span class="token keyword">const</span> <span class="token function-variable function">Count</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">prop</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>CountConsumer<span class="token operator">></span> <span class="token punctuation">{</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span> count <span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator"><</span>span<span class="token operator">></span><span class="token punctuation">{</span>count<span class="token punctuation">}</span><span class="token operator"><</span><span class="token operator">/</span>span<span class="token operator">></span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token operator"><</span><span class="token operator">/</span>CountConsumer<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> </code></pre> <pre><code class="prism language-javascript"><span class="token comment">// 组合</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>CountProvider<span class="token operator">></span> <span class="token operator"><</span>CountButton type<span class="token operator">=</span><span class="token string">'decrease'</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>Count <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>CountButton type<span class="token operator">=</span><span class="token string">'increase'</span> <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>CountProvider<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> <pre><code>复杂的非父子组件通信在react中很难处理,多组件间的数据共享也不好处理,在实际的工作中我们会使用flux、redux、mobx来实现 </code></pre> <h3>HOC(高阶组件)</h3> <p>Higher-Order Components就是一个函数,传给它一个组件,它返回一个新的组件。</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> NewComponent <span class="token operator">=</span> <span class="token function">higherOrderComponent</span><span class="token punctuation">(</span>YourComponent<span class="token punctuation">)</span> </code></pre> <p>比如,我们想要我们的组件通过自动注入一个版权信息。</p> <pre><code class="prism language-javascript"><span class="token comment">// withCopyright.js 定义一个高阶组件</span> <span class="token keyword">import</span> React<span class="token punctuation">,</span> <span class="token punctuation">{</span> Component<span class="token punctuation">,</span> Fragment <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'react'</span> <span class="token keyword">const</span> <span class="token function-variable function">withCopyright</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">WrappedComponent</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">class</span> <span class="token class-name">NewComponent</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>Fragment<span class="token operator">></span> <span class="token operator"><</span>WrappedComponent <span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>div<span class="token operator">></span>好好学习,天天向上 <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>Fragment<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">export</span> <span class="token keyword">default</span> withCopyright </code></pre> <pre><code class="prism language-javascript"><span class="token comment">// 使用方式</span> <span class="token keyword">import</span> withCopyright <span class="token keyword">from</span> <span class="token string">'./withCopyright'</span> <span class="token keyword">class</span> <span class="token class-name">App</span> <span class="token keyword">extends</span> <span class="token class-name">Component</span> <span class="token punctuation">{</span> <span class="token function">render</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">(</span> <span class="token operator"><</span>div<span class="token operator">></span> <span class="token operator"><</span>h1<span class="token operator">></span>Awesome React<span class="token operator"><</span><span class="token operator">/</span>h1<span class="token operator">></span> <span class="token operator"><</span>p<span class="token operator">></span>React<span class="token punctuation">.</span>js是一个构建用户界面的库<span class="token operator"><</span><span class="token operator">/</span>p<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> CopyrightApp <span class="token operator">=</span> <span class="token function">withCopyright</span><span class="token punctuation">(</span>App<span class="token punctuation">)</span> </code></pre> <p>这样只要我们有需要用到版权信息的组件,都可以直接使用withCopyright这个高阶组件包裹即可。<br> 在这里要讲解在CRA 中配置装饰器模式的支持。</p> <h2>状态管理</h2> <h3>传统MVC框架的缺陷</h3> <p><strong>什么是MVC?</strong></p> <p>MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。<br> V即View视图是指用户看到并与之交互的界面。<br> M即Model模型是管理数据 ,很多业务逻辑都在模型中完成。在MVC的三个部件中,模型拥有最多的处理任务。<br> C即Controller控制器是指控制器接受用户的输入并调用模型和视图去完成用户的需求,控制器本身不输出任何东西和做任何处理。它只是接收请求并决定调用哪个模型构件去处理请求,然后再确定用哪个视图来显示返回的数据。<br> <strong>MVC只是看起来很美</strong><br> MVC框架的数据流很理想,请求先到Controller, 由Controller调用Model中的数据交给View进行渲染,但是在实际的项目中,又是允许Model和View直接通信的</p> <h3>Flux</h3> <p>在2013年,Facebook让React亮相的同时推出了Flux框架,React的初衷实际上是用来替代jQuery的,Flux实际上就可以用来替代Backbone.js,Ember.js等一系列MVC架构的前端JS框架。<br> 其实Flux在React里的应用就类似于Vue中的Vuex的作用,但是在Vue中,Vue是完整的mvvm框架,而Vuex只是一个全局的插件。<br> React只是一个MVC中的V(视图层),只管页面中的渲染,一旦有数据管理的时候,React本身的能力就不足以支撑复杂组件结构的项目,在传统的MVC中,就需要用到Model和Controller。Facebook对于当时世面上的MVC框架并不满意,于是就有了Flux, 但Flux并不是一个MVC框架,他是一种新的思想。</p> <ul> <li>View: 视图层</li> <li>ActionCreator(动作创造者):视图层发出的消息(比如mouseClick)</li> <li>Dispatcher(派发器):用来接收Actions、执行回调函数</li> <li>Store(数据层):用来存放应用的状态,一旦发生变动,就提醒Views要更新页面</li> <li>Flux的流程:</li> </ul> <ol> <li>组件获取到store中保存的数据挂载在自己的状态上</li> <li>用户产生了操作,调用actions的方法</li> <li>actions接收到了用户的操作,进行一系列的逻辑代码、异步操作</li> <li>然后actions会创建出对应的action,action带有标识性的属性</li> <li>actions调用dispatcher的dispatch方法将action传递给dispatcher</li> <li>dispatcher接收到action并根据标识信息判断之后,调用store的更改数据的方法</li> <li>store的方法被调用后,更改状态,并触发自己的某一个事件</li> <li>store更改状态后事件被触发,该事件的处理程序会通知view去获取最新的数据</li> </ol> <h3>Redux</h3> <p>React 只是 DOM 的一个抽象层,并不是 Web 应用的完整解决方案。有两个方面,它没涉及。</p> <ul> <li> <p>代码结构</p> </li> <li> <p>组件之间的通信</p> </li> <li> <p>2013年 Facebook 提出了 Flux 架构的思想,引发了很多的实现。2015年,Redux 出现,将<br> Flux 与函数式编程结合一起,很短时间内就成为了最热门的前端架构。 如果你不知道是否需要 Redux,那就是不需要它 只有遇到<br> React 实在解决不了的问题,你才需要 Redux 简单说,如果你的UI层非常简单,没有很多互动,Redux<br> 就是不必要的,用了反而增加复杂性。</p> </li> <li> <p>用户的使用方式非常简单</p> </li> <li> <p>用户之间没有协作</p> </li> <li> <p>不需要与服务器大量交互,也没有使用 WebSocket</p> </li> <li> <p>视图层(View)只从单一来源获取数据<br> <strong>需要使用Redux的项目:</strong></p> </li> <li> <p>用户的使用方式复杂</p> </li> <li> <p>不同身份的用户有不同的使用方式(比如普通用户和管理员)</p> </li> <li> <p>多个用户之间可以协作</p> </li> <li> <p>与服务器大量交互,或者使用了WebSocket</p> </li> <li> <p>View要从多个来源获取数据</p> </li> </ul> <p><strong>从组件层面考虑,什么样子的需要Redux:</strong></p> <ul> <li>某个组件的状态,需要共享 某个状态需要在任何地方都可以拿到</li> <li>一个组件需要改变全局状态</li> <li>一个组件需要改变另一个组件的状态</li> </ul> <p><strong>Redux的设计思想:</strong><br> 1. Web 应用是一个状态机,视图与状态是一一对应的。<br> 2. 所有的状态,保存在一个对象里面(唯一数据源)。</p> <pre><code class="prism language-bash"> 注意:flux、redux都不是必须和react搭配使用的,因为flux和redux是完整的架构,在学习react的时候,只是将react的组件作为redux中的视图层去使用了。 </code></pre> <p><strong>Redux的使用的三大原则:</strong></p> <ul> <li>Single Source of Truth(唯一的数据源)</li> <li>State is read-only(状态是只读的)</li> <li>Changes are made with pure function(数据的改变必须通过纯函数完成)</li> </ul> <h2>自己实现Redux</h2> <p>这个部分,可以根据班级情况看是否讲解。对于学生使用redux有很大的帮助。不使用react,直接使用原生的html/js来写一个简易的的redux<br> 基本的状态管理及数据渲染</p> <pre><code class="prism language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>X-UA-Compatible<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ie=edge<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Redux principle 01<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>redux principle<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>counter<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dispatch({type: <span class="token punctuation">'</span>COUNT_DECREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>-<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>add<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>dispatch({type: <span class="token punctuation">'</span>COUNT_INCREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>+<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"> <span class="token comment">// 定义一个计数器的状态</span> <span class="token keyword">const</span> countState <span class="token operator">=</span> <span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token number">10</span> <span class="token punctuation">}</span> <span class="token comment">// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态</span> <span class="token keyword">const</span> <span class="token function-variable function">changeState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">switch</span><span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 处理减</span> <span class="token keyword">case</span> <span class="token string">'COUNT_DECREMENT'</span><span class="token operator">:</span> countState<span class="token punctuation">.</span>count <span class="token operator">-=</span> action<span class="token punctuation">.</span>number <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token comment">// 处理加</span> <span class="token keyword">case</span> <span class="token string">'COUNT_INCREMENT'</span><span class="token operator">:</span> countState<span class="token punctuation">.</span>count <span class="token operator">+=</span> action<span class="token punctuation">.</span>number <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 定义一个方法用于渲染计数器的dom</span> <span class="token keyword">const</span> <span class="token function-variable function">renderCount</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> countDom <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#count'</span><span class="token punctuation">)</span> countDom<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> state<span class="token punctuation">.</span>count <span class="token punctuation">}</span> <span class="token comment">// 首次渲染数据</span> <span class="token function">renderCount</span><span class="token punctuation">(</span>countState<span class="token punctuation">)</span> <span class="token comment">// 定义一个dispatch的方法,接收到动作之后,自动调用</span> <span class="token keyword">const</span> <span class="token function-variable function">dispatch</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">changeState</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span> <span class="token function">renderCount</span><span class="token punctuation">(</span>countState<span class="token punctuation">)</span> <span class="token punctuation">}</span> </span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span> </code></pre> <p>创建createStore方法</p> <pre><code class="prism language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>X-UA-Compatible<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ie=edge<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Redux principle 02<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>redux principle<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>counter<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>store.dispatch({type: <span class="token punctuation">'</span>COUNT_DECREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>-<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>add<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>store.dispatch({type: <span class="token punctuation">'</span>COUNT_INCREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>+<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"> <span class="token comment">// 定义一个方法,用于集中管理state和dispatch</span> <span class="token keyword">const</span> <span class="token function-variable function">createStore</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> changeState</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// getState用于获取状态</span> <span class="token keyword">const</span> <span class="token function-variable function">getState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> state <span class="token comment">// 定义一个监听器,用于管理一些方法</span> <span class="token keyword">const</span> listeners <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token keyword">const</span> <span class="token function-variable function">subscribe</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">listener</span><span class="token punctuation">)</span> <span class="token operator">=></span> listeners<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>listener<span class="token punctuation">)</span> <span class="token comment">// 定义一个dispatch方法,让每次有action传入的时候返回render执行之后的结果</span> <span class="token keyword">const</span> <span class="token function-variable function">dispatch</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// 调用changeState来处理数据</span> <span class="token function">changeState</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> action<span class="token punctuation">)</span> <span class="token comment">// 让监听器里的所以方法运行</span> listeners<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">listener</span> <span class="token operator">=></span> <span class="token function">listener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> getState<span class="token punctuation">,</span> dispatch<span class="token punctuation">,</span> subscribe <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 定义一个计数器的状态</span> <span class="token keyword">const</span> countState <span class="token operator">=</span> <span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token number">10</span> <span class="token punctuation">}</span> <span class="token comment">// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态</span> <span class="token keyword">const</span> <span class="token function-variable function">changeState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">switch</span><span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 处理减</span> <span class="token keyword">case</span> <span class="token string">'COUNT_DECREMENT'</span><span class="token operator">:</span> state<span class="token punctuation">.</span>count <span class="token operator">-=</span> action<span class="token punctuation">.</span>number <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token comment">// 处理加</span> <span class="token keyword">case</span> <span class="token string">'COUNT_INCREMENT'</span><span class="token operator">:</span> state<span class="token punctuation">.</span>count <span class="token operator">+=</span> action<span class="token punctuation">.</span>number <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 创建一个store</span> <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>countState<span class="token punctuation">,</span> changeState<span class="token punctuation">)</span> <span class="token comment">// 定义一个方法用于渲染计数器的dom</span> <span class="token keyword">const</span> <span class="token function-variable function">renderCount</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> countDom <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#count'</span><span class="token punctuation">)</span> countDom<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>count <span class="token punctuation">}</span> <span class="token comment">// 初次渲染数据</span> <span class="token function">renderCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 监听,只要有dispatch,这个方法就会自动运行</span> store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>renderCount<span class="token punctuation">)</span> </span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span> </code></pre> <p>让changeState方法变为一个纯函数</p> <pre><code class="prism language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>X-UA-Compatible<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ie=edge<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Redux principle 03<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>redux principle<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>counter<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>store.dispatch({type: <span class="token punctuation">'</span>COUNT_DECREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>-<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>add<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>store.dispatch({type: <span class="token punctuation">'</span>COUNT_INCREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>+<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"> <span class="token comment">// 定义一个方法,用于集中管理state和dispatch</span> <span class="token keyword">const</span> <span class="token function-variable function">createStore</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> changeState</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// getState用于获取状态</span> <span class="token keyword">const</span> <span class="token function-variable function">getState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> state <span class="token comment">// 定义一个监听器,用于管理一些方法</span> <span class="token keyword">const</span> listeners <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token keyword">const</span> <span class="token function-variable function">subscribe</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">listener</span><span class="token punctuation">)</span> <span class="token operator">=></span> listeners<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>listener<span class="token punctuation">)</span> <span class="token comment">// 定义一个dispatch方法,让每次有action传入的时候返回render执行之后的结果</span> <span class="token keyword">const</span> <span class="token function-variable function">dispatch</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// 调用changeState来处理数据</span> state <span class="token operator">=</span> <span class="token function">changeState</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> action<span class="token punctuation">)</span> <span class="token comment">// 让监听器里的所有方法运行</span> listeners<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">listener</span> <span class="token operator">=></span> <span class="token function">listener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> getState<span class="token punctuation">,</span> dispatch<span class="token punctuation">,</span> subscribe <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 定义一个计数器的状态</span> <span class="token keyword">const</span> countState <span class="token operator">=</span> <span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token number">10</span> <span class="token punctuation">}</span> <span class="token comment">// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态</span> <span class="token keyword">const</span> <span class="token function-variable function">changeState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">switch</span><span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 处理减</span> <span class="token keyword">case</span> <span class="token string">'COUNT_DECREMENT'</span><span class="token operator">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> count<span class="token operator">:</span> state<span class="token punctuation">.</span>count <span class="token operator">-</span> action<span class="token punctuation">.</span>number <span class="token punctuation">}</span> <span class="token comment">// 处理加</span> <span class="token keyword">case</span> <span class="token string">'COUNT_INCREMENT'</span><span class="token operator">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> count<span class="token operator">:</span> state<span class="token punctuation">.</span>count <span class="token operator">+</span> action<span class="token punctuation">.</span>number <span class="token punctuation">}</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">return</span> state <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 创建一个store</span> <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>countState<span class="token punctuation">,</span> changeState<span class="token punctuation">)</span> <span class="token comment">// 定义一个方法用于渲染计数器的dom</span> <span class="token keyword">const</span> <span class="token function-variable function">renderCount</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> countDom <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#count'</span><span class="token punctuation">)</span> countDom<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>count <span class="token punctuation">}</span> <span class="token comment">// 初次渲染数据</span> <span class="token function">renderCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 监听,只要有dispatch,这个方法就会自动运行</span> store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>renderCount<span class="token punctuation">)</span> </span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span> </code></pre> <p>合并state和changeState(最终版)</p> <pre><code class="prism language-html"><span class="token doctype"><span class="token punctuation"><!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>en<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>UTF-8<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>viewport<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>width=device-width, initial-scale=1.0<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>X-UA-Compatible<span class="token punctuation">"</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ie=edge<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>title</span><span class="token punctuation">></span></span>Redux principle 04<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>title</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>head</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>h1</span><span class="token punctuation">></span></span>redux principle<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>h1</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>counter<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>store.dispatch({type: <span class="token punctuation">'</span>COUNT_DECREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>-<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>count<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>span</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>add<span class="token punctuation">"</span></span> <span class="token attr-name">onclick</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>store.dispatch({type: <span class="token punctuation">'</span>COUNT_INCREMENT<span class="token punctuation">'</span>, number: 10})<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>+<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>span</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script"><span class="token language-javascript"> <span class="token comment">// 定义一个方法,用于集中管理state和dispatch, changeState改名了,专业的叫法是reducer</span> <span class="token keyword">const</span> <span class="token function-variable function">createStore</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">reducer</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// 定义一个初始的state</span> <span class="token keyword">let</span> state <span class="token operator">=</span> <span class="token keyword">null</span> <span class="token comment">// getState用于获取状态</span> <span class="token keyword">const</span> <span class="token function-variable function">getState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> state <span class="token comment">// 定义一个监听器,用于管理一些方法</span> <span class="token keyword">const</span> listeners <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token keyword">const</span> <span class="token function-variable function">subscribe</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">listener</span><span class="token punctuation">)</span> <span class="token operator">=></span> listeners<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>listener<span class="token punctuation">)</span> <span class="token comment">// 定义一个dispatch方法,让每次有action传入的时候返回reducer执行之后的结果</span> <span class="token keyword">const</span> <span class="token function-variable function">dispatch</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// 调用reducer来处理数据</span> state <span class="token operator">=</span> <span class="token function">reducer</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> action<span class="token punctuation">)</span> <span class="token comment">// 让监听器里的所有方法运行</span> listeners<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">listener</span> <span class="token operator">=></span> <span class="token function">listener</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token comment">// 初始化state</span> <span class="token function">dispatch</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> getState<span class="token punctuation">,</span> dispatch<span class="token punctuation">,</span> subscribe <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 定义一个计数器的状态</span> <span class="token keyword">const</span> countState <span class="token operator">=</span> <span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token number">10</span> <span class="token punctuation">}</span> <span class="token comment">// 定一个方法叫changeState,用于处理state的数据,每次都返回一个新的状态</span> <span class="token keyword">const</span> <span class="token function-variable function">changeState</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token comment">// 如果state是null, 就返回countState</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>state<span class="token punctuation">)</span> <span class="token keyword">return</span> countState <span class="token keyword">switch</span><span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 处理减</span> <span class="token keyword">case</span> <span class="token string">'COUNT_DECREMENT'</span><span class="token operator">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> count<span class="token operator">:</span> state<span class="token punctuation">.</span>count <span class="token operator">-</span> action<span class="token punctuation">.</span>number <span class="token punctuation">}</span> <span class="token comment">// 处理加</span> <span class="token keyword">case</span> <span class="token string">'COUNT_INCREMENT'</span><span class="token operator">:</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> count<span class="token operator">:</span> state<span class="token punctuation">.</span>count <span class="token operator">+</span> action<span class="token punctuation">.</span>number <span class="token punctuation">}</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">return</span> state <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 创建一个store</span> <span class="token keyword">const</span> store <span class="token operator">=</span> <span class="token function">createStore</span><span class="token punctuation">(</span>changeState<span class="token punctuation">)</span> <span class="token comment">// 定义一个方法用于渲染计数器的dom</span> <span class="token keyword">const</span> <span class="token function-variable function">renderCount</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> countDom <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#count'</span><span class="token punctuation">)</span> countDom<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> store<span class="token punctuation">.</span><span class="token function">getState</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span>count <span class="token punctuation">}</span> <span class="token comment">// 初次渲染数据</span> <span class="token function">renderCount</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 监听,只要有dispatch,renderCount就会自动运行</span> store<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>renderCount<span class="token punctuation">)</span> </span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>body</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>html</span><span class="token punctuation">></span></span> </code></pre> <h3>使用Redux框架</h3> <p><strong>Redux的流程:</strong></p> <p>1.store通过reducer创建了初始状态<br> 2.view通过store.getState()获取到了store中保存的state挂载在了自己的状态上<br> 3.用户产生了操作,调用了actions 的方法<br> 4.actions的方法被调用,创建了带有标示性信息的action<br> 5.actions将action通过调用store.dispatch方法发送到了reducer中<br> 6.reducer接收到action并根据标识信息判断之后返回了新的state<br> 7.store的state被reducer更改为新state的时候,store.subscribe方法里的回调函数会执行,此时就可以通知view去重新获取state</p> <p><strong>Reducer必须是一个纯函数:</strong></p> <p>Reducer 函数最重要的特征是,它是一个纯函数。也就是说,只要是同样的输入,必定得到同样的输出。Reducer不是只有Redux里才有,之前学的数组方法reduce, 它的第一个参数就是一个reducer<br> 纯函数是函数式编程的概念,必须遵守以下一些约束。</p> <ul> <li>不得改写参数</li> <li>不能调用系统 I/O 的API</li> <li>不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果 由于 Reducer<br> 是纯函数,就可以保证同样的State,必定得到同样的 View。但也正因为这一点,Reducer 函数里面不能改变<br> State,必须返回一个全新的对象,请参考下面的写法。</li> </ul> <pre><code class="prism language-javascript"><span class="token comment">// State 是一个对象</span> <span class="token keyword">function</span> <span class="token function">reducer</span><span class="token punctuation">(</span><span class="token parameter">state <span class="token operator">=</span> defaultState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> Object<span class="token punctuation">.</span><span class="token function">assign</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> state<span class="token punctuation">,</span> <span class="token punctuation">{</span> thingToChange <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 或者</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token operator">...</span>state<span class="token punctuation">,</span> <span class="token operator">...</span>newState <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// State 是一个数组</span> <span class="token keyword">function</span> <span class="token function">reducer</span><span class="token punctuation">(</span><span class="token parameter">state <span class="token operator">=</span> defaultState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token operator">...</span>state<span class="token punctuation">,</span> newItem<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> </code></pre> <p>最好把 State 对象设成只读。要得到新的 State,唯一办法就是生成一个新对象。这样的好处是,任何时候,与某个 View 对应的 State 总是一个不变(immutable)的对象。<br> 我们可以通过在createStore中传入第二个参数来设置默认的state,但是这种形式只适合于只有一个reducer的时候。<br> <strong>划分reducer:</strong><br> 因为一个应用中只能有一个大的state,这样的话reducer中的代码将会特别特别的多,那么就可以使用combineReducers方法将已经分开的reducer合并到一起</p> <pre><code> 注意: 分离reducer的时候,每一个reducer维护的状态都应该不同 通过store.getState获取到的数据也是会按照reducers去划分的 划分多个reducer的时候,默认状态只能创建在reducer中,因为划分reducer的目的,就是为了让每一个reducer都去独立管理一部分状态 最开始一般基于计数器的例子讲解redux的基本使用即可。 关于action/reducer/store的更多概念,请查看官网 Redux异步 通常情况下,action只是一个对象,不能包含异步操作,这导致了很多创建action的逻辑只能写在组件中,代码量较多也不便于复用,同时对该部分代码测试的时候也比较困难,组件的业务逻辑也不清晰,使用中间件了之后,可以通过actionCreator异步编写action,这样代码就会拆分到actionCreator中,可维护性大大提高,可以方便于测试、复用,同时actionCreator还集成了异步操作中不同的action派发机制,减少编码过程中的代码量 </code></pre> <p><strong>常见的异步库:</strong></p> <ul> <li>Redux-thunk(就讲这个)</li> <li>Redux-saga</li> <li>Redux-effects</li> <li>Redux-side-effects</li> <li>Redux-loop Redux-observable …</li> <li>基于Promise的异步库: Redux-promise</li> <li>Redux-promises</li> <li>Redux-simple-promise</li> <li>Redux-promise-middleware</li> </ul> <h3>容器组件(Smart/Container Components)和展示组件(Dumb/Presentational Components)</h3> <table> <thead> <tr> <th align="right"></th> <th align="left">展示组件</th> <th align="left">容器组件</th> </tr> </thead> <tbody> <tr> <td align="right">作用</td> <td align="left">描述如何展现(骨架、样式)</td> <td align="left">描述如何运行(数据获取、状态更新)</td> </tr> <tr> <td align="right">直接使用 Redux</td> <td align="left">否</td> <td align="left">是</td> </tr> <tr> <td align="right">数据来源</td> <td align="left">props</td> <td align="left">监听 Redux state</td> </tr> <tr> <td align="right">数据修改</td> <td align="left">从 props 调用回调函数</td> <td align="left">向 Redux 派发 actions</td> </tr> <tr> <td align="right">调用方式</td> <td align="left">手动</td> <td align="left">通常由 React Redux 生成</td> </tr> </tbody> </table> <h4>使用react-redux</h4> <p>可以先结合context来手动连接react和redux。<br> react-redux提供两个核心的api:</p> <ul> <li>Provider: 提供store</li> <li>connect: 用于连接容器组件和展示组件</li> </ul> <ol> <li>Provider<br> 根据单一store原则 ,一般只会出现在整个应用程序的最顶层。</li> <li>connect<br> 语法格式为<br> connect(mapStateToProps?, mapDispatchToProps?, mergeProps?, options?)(component)<br> 一般来说只会用到前面两个,它的作用是:</li> </ol> <ul> <li>把store.getState()的状态转化为展示组件的props</li> <li>把actionCreators转化为展示组件props上的方法</li> </ul> <pre><code class="prism language-csharp">特别强调: 官网上的第二个参数为mapDispatchToProps<span class="token punctuation">,</span> 实际上就是actionCreators 只要上层中有Provider组件并且提供了store<span class="token punctuation">,</span> 那么,子孙级别的任何组件,要想使用store里的状态,都可以通过connect方法进行连接。如果只是想连接actionCreators,可以第一个参数传递为<span class="token keyword">null</span> </code></pre> <h4>React Router</h4> <p>React Router现在的版本是5, 于2019年3月21日搞笑的发布,搞笑的官网链接, 本来是要发布4.4的版本的,结果成了5。从4开始,使用方式相对于之前版本的思想有所不同。之前版本的思想是传统的思想:路由应该统一在一处渲染, Router 4之后是这样的思想:一切皆组件<br> React Router包含了四个包:</p> <table> <thead> <tr> <th>包名</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td>react-router</td> <td>React Router核心api</td> </tr> <tr> <td>react-router-dom</td> <td>React Router的DOM绑定,在浏览器中运行不需要额外安装react-router</td> </tr> <tr> <td>react-router-native</td> <td>React Native 中使用,而实际的应用中,其实不会使用这个。</td> </tr> <tr> <td>react-router-config</td> <td>静态路由的配置</td> </tr> </tbody> </table> <p>主要使用<strong>react-router-dom</strong></p> <p><strong>使用方式</strong></p> <p>正常情况下,直接按照官网的demo就理解 路由的使用方式,有几个点需要特别的强调:</p> <ul> <li> <p>Route组件的exact属性</p> </li> <li> <p>exact属性标识是否为严格匹配, 为true是表示严格匹配,为false时为正常匹配。</p> </li> <li> <p>Route组件的render属性而不是component属性</p> </li> <li> <p>怎么在渲染组件的时候,对组件传递属性呢?使用component的方式是不能直接在组件上添加属性的。<br> 所以,React<br> Router的Route组件提供了另一种渲染组件的方式 render, 这个常用于页面组件级别的权限管理。</p> </li> <li> <p>路由的参数传递与获取</p> </li> <li> <p>Switch组件 总是渲染第一个匹配到的组件</p> </li> <li> <p>处理404与默认页</p> </li> <li> <p>withRoute高阶组件的使用</p> </li> <li> <p>管理一个项目路由的方法</p> </li> <li> <p>code spliting</p> </li> <li> <p>HashRouter和BrowserRouter的区别,前端路由和后端路由的区别。这个在Vue里应该有讲过了。</p> </li> </ul> <h4>React Router基本原理</h4> <p>React Router甚至大部分的前端路由都是依赖于history.js的,它是一个独立的第三方js库。可以用来兼容在不同浏览器、不同环境下对历史记录的管理,拥有统一的API。</p> <ul> <li>老浏览器的history: 通过hash来存储在不同状态下的history信息,对应createHashHistory,通过检测location.hash的值的变化,使用location.replace方法来实现url跳转。通过注册监听window对象上的hashChange事件来监听路由的变化,实现历史记录的回退。</li> <li>高版本浏览器: 利用HTML5里面的history,对应createBrowserHistory, 使用包括pushState, replaceState方法来进行跳转。通过注册监听window对象上的popstate事件来监听路由的变化,实现历史记录的回退。</li> <li>node环境下: 在内存中进行历史记录的存储,对应createMemoryHistory。直接在内存里push和pop状态。</li> </ul> <h4>Immutable.js</h4> <p><strong>JavaScript数据修改的问题</strong></p> <p>看一段大家熟悉的代码</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> str<span class="token operator">:</span> <span class="token string">'好好学习'</span><span class="token punctuation">,</span> obj<span class="token operator">:</span> <span class="token punctuation">{</span> y<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> newState <span class="token operator">=</span> state console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>newState <span class="token operator">===</span> state<span class="token punctuation">)</span> <span class="token comment">// true</span> </code></pre> <p>由于js的对象和数组都是引用类型。所以newState的state实际上是指向于同一块内存地址的, 所以结果是newState和state是相等的。<br> 尝试修改一下数据</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> str<span class="token operator">:</span> <span class="token string">'好好学习'</span><span class="token punctuation">,</span> obj<span class="token operator">:</span> <span class="token punctuation">{</span> y<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> newState <span class="token operator">=</span> state newState<span class="token punctuation">.</span>str <span class="token operator">=</span> <span class="token string">'好好学习,天天向上'</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>str<span class="token punctuation">,</span> newState<span class="token punctuation">.</span>str<span class="token punctuation">)</span> </code></pre> <p>可以看到,newState的修改也会引起state的修改。要解决这个问题,js中提供了另一种修改数据的方式,要修改一个数据之前先制作一份数据的拷贝,像这样</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> str<span class="token operator">:</span> <span class="token string">'好好学习'</span><span class="token punctuation">,</span> obj<span class="token operator">:</span> <span class="token punctuation">{</span> y<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> newState <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">assign</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> state<span class="token punctuation">)</span> newState<span class="token punctuation">.</span>str <span class="token operator">=</span> <span class="token string">'好好学习,天天向上'</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">.</span>str<span class="token punctuation">,</span> newState<span class="token punctuation">.</span>str<span class="token punctuation">)</span> </code></pre> <p>我们可以使用很多方式在js中复制数据,比如…, Object.assign, Object.freeze, slice, concat, map, filter, reduce等方式进行复制,但这些都是浅拷贝,就是只拷贝第一层数据,更深层的数据还是同一个引用,比如:</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> str<span class="token operator">:</span> <span class="token string">'好好学习'</span><span class="token punctuation">,</span> obj<span class="token operator">:</span> <span class="token punctuation">{</span> y<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> newState <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">assign</span><span class="token punctuation">(</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span> state<span class="token punctuation">)</span> newState<span class="token punctuation">.</span>obj<span class="token punctuation">.</span>y <span class="token operator">=</span> <span class="token number">2</span> newState<span class="token punctuation">.</span>arr<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> newState<span class="token punctuation">)</span> </code></pre> <p>可以看到,当在更改newState更深层次的数据的时候,还是会影响到state的值。如果要深层复制,就得一层一层的做递归拷贝,这是一个复杂的问题。虽然有些第三方的库已经帮我们做好了,比如lodash的cloneDeep方法。深拷贝是非常消耗性能的。</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> cloneDeep <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'lodash'</span> <span class="token keyword">const</span> state <span class="token operator">=</span> <span class="token punctuation">{</span> str<span class="token operator">:</span> <span class="token string">'好好学习'</span><span class="token punctuation">,</span> obj<span class="token operator">:</span> <span class="token punctuation">{</span> y<span class="token operator">:</span> <span class="token number">1</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> arr<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> newState <span class="token operator">=</span> <span class="token function">cloneDeep</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span> newState<span class="token punctuation">.</span>obj<span class="token punctuation">.</span>y <span class="token operator">=</span> <span class="token number">2</span> newState<span class="token punctuation">.</span>arr<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> newState<span class="token punctuation">)</span> </code></pre> <p><strong>什么是不可变数据</strong><br> 不可变数据 (Immutable Data )就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。Immutable 实现的原理是持久化数据结构( Persistent Data Structure),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变。同时为了避免 deepCopy 把所有节点都复制一遍带来的s性能损耗,Immutable 使用了 结构共享(Structural Sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。</p> <p><strong>immutable.js的优缺点</strong><br> 优点:</p> <ul> <li>降低mutable带来的复杂度</li> <li>节省内存</li> <li>历史追溯性(时间旅行):时间旅行指的是,每时每刻的值都被保留了,想回退到哪一步只要简单的将数据取出就行,想一下如果现在页面有个撤销的操作,撤销前的数据被保留了,只需要取出就行,这个特性在redux或者flux中特别有用</li> <li>拥抱函数式编程:immutable本来就是函数式编程的概念,纯函数式编程的特点就是,只要输入一致,输出必然一致,相比于面向对象,这样开发组件和调试更方便。推荐一本函数式编程的在线免费书《JS 函数式编程指南》, 此书可以推荐给学生做为课外补充阅读。</li> </ul> <p>缺点:</p> <ul> <li>需要重新学习api</li> <li>资源包大小增加(源码5000行左右)</li> <li>容易与原生对象混淆:由于api与原生不同,混用的话容易出错。</li> </ul> <p><strong>使用Immutable.js</strong></p> <p>参考官网重点讲解数据不可变数据的创建、更新及比较方式 。对于就业班来说,掌握以下知识点即可。</p> <p><strong>Map</strong></p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Map <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'immutable'</span> <span class="token keyword">const</span> map <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> c<span class="token operator">:</span> <span class="token number">3</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> newMap <span class="token operator">=</span> map<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">,</span> <span class="token number">20</span><span class="token punctuation">)</span> <span class="token comment">// immutable数据每次都是生成新的再重新调用set进行修改,所以需要 重新赋值给一个新的变量</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>map<span class="token punctuation">,</span> newMap<span class="token punctuation">)</span> <span class="token comment">// immutable.Map不是原生的对象</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>map<span class="token punctuation">.</span>b<span class="token punctuation">,</span> newMap<span class="token punctuation">.</span>b<span class="token punctuation">)</span> <span class="token comment">// immutable.Map不是原生的对象, 所以是undefined</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">,</span> newMap<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 要取值,需要调用get(key)方法,可以看到,两个值不一样</span> <span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> c<span class="token operator">:</span> <span class="token number">3</span> <span class="token punctuation">}</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>Map<span class="token punctuation">.</span><span class="token function">isMap</span><span class="token punctuation">(</span>map<span class="token punctuation">)</span><span class="token punctuation">,</span> Map<span class="token punctuation">.</span><span class="token function">isMap</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// true false, 使用Map.isMap来判断是否是一个immutable.Map类型</span> </code></pre> <p><strong>List</strong></p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> List <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'immutable'</span> <span class="token keyword">const</span> list <span class="token operator">=</span> <span class="token function">List</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token keyword">const</span> newList <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>list<span class="token punctuation">,</span> newList<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>list<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">,</span> newList<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">// undefined undefined</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>list<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">,</span> newList<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token number">4</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// undefined 5</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>list<span class="token punctuation">.</span>size<span class="token punctuation">,</span> newList<span class="token punctuation">.</span>size<span class="token punctuation">)</span> <span class="token comment">// 4 5</span> <span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>List<span class="token punctuation">.</span><span class="token function">isList</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span><span class="token punctuation">,</span> List<span class="token punctuation">.</span><span class="token function">isList</span><span class="token punctuation">(</span>arr<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// true false</span> </code></pre> <p><strong>equals & is</strong></p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Map<span class="token punctuation">,</span> is <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'immutable'</span> <span class="token keyword">const</span> map <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> c<span class="token operator">:</span> <span class="token number">3</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> anotherMap <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> c<span class="token operator">:</span> <span class="token number">3</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>map <span class="token operator">==</span> anotherMap<span class="token punctuation">)</span> <span class="token comment">// false</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>map <span class="token operator">===</span> anotherMap<span class="token punctuation">)</span> <span class="token comment">// false</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>map<span class="token punctuation">.</span><span class="token function">equals</span><span class="token punctuation">(</span>anotherMap<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 使用equals进行比较 true</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">is</span><span class="token punctuation">(</span>map<span class="token punctuation">,</span> anotherMap<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 使用is进行比较 true</span> </code></pre> <p><strong>List常用api</strong></p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> List <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'immutable'</span> <span class="token keyword">const</span> list <span class="token operator">=</span> <span class="token function">List</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token keyword">const</span> list1 <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token number">5</span><span class="token punctuation">)</span> <span class="token keyword">const</span> list2 <span class="token operator">=</span> list1<span class="token punctuation">.</span><span class="token function">unshift</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">const</span> list3 <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">concat</span><span class="token punctuation">(</span>list1<span class="token punctuation">,</span> list2<span class="token punctuation">)</span> <span class="token keyword">const</span> list4 <span class="token operator">=</span> list<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">v</span> <span class="token operator">=></span> v <span class="token operator">*</span> <span class="token number">2</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>list<span class="token punctuation">.</span>size<span class="token punctuation">,</span> list1<span class="token punctuation">.</span>size<span class="token punctuation">,</span> list2<span class="token punctuation">.</span>size<span class="token punctuation">,</span> list3<span class="token punctuation">.</span>size<span class="token punctuation">,</span> list4<span class="token punctuation">.</span><span class="token function">toJS</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 4 5 6 15, [2, 4, 6, 8]</span> </code></pre> <p><strong>Map常用api</strong></p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Map <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'immutable'</span> <span class="token keyword">const</span> alpha <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token number">2</span><span class="token punctuation">,</span> c<span class="token operator">:</span> <span class="token number">3</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> objKeys <span class="token operator">=</span> alpha<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">v<span class="token punctuation">,</span> k</span><span class="token punctuation">)</span> <span class="token operator">=></span> k<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>objKeys<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// a, b, c</span> <span class="token keyword">const</span> map1 <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> map2 <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> c<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span> d<span class="token operator">:</span> <span class="token number">4</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">const</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span> d<span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span> e<span class="token operator">:</span> <span class="token number">50</span> <span class="token punctuation">}</span> <span class="token keyword">const</span> mergedMap <span class="token operator">=</span> map1<span class="token punctuation">.</span><span class="token function">merge</span><span class="token punctuation">(</span>map2<span class="token punctuation">,</span> obj<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>mergedMap<span class="token punctuation">.</span><span class="token function">toObject</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>mergedMap<span class="token punctuation">.</span><span class="token function">toJS</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> </code></pre> <p><strong>在redux中使用immutable.js</strong><br> redux官网推荐使用redux-immutable进行redux和immutable的集成。几个注意点:<br> redux中,利用combineReducers来合并多个reduce, redux自带的combineReducers只支持原生js形式的,所以需要使用redux-immutable提供的combineReducers来代替</p> <pre><code class="prism language-javascript"><span class="token comment">// 使用redux-immutable提供的combineReducers方法替换redux里的combineReducers</span> <span class="token keyword">import</span> <span class="token punctuation">{</span>combineReducers<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'redux-immutable'</span> <span class="token keyword">import</span> reducerOne <span class="token keyword">from</span> <span class="token string">'./reducerOne'</span> <span class="token keyword">import</span> reducerTwo <span class="token keyword">from</span> <span class="token string">'./reducerTwo'</span> <span class="token keyword">const</span> rootReducer <span class="token operator">=</span> <span class="token function">combineReducers</span><span class="token punctuation">(</span><span class="token punctuation">{</span> reducerOne<span class="token punctuation">,</span> reducerTwo <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">export</span> <span class="token keyword">default</span> rootReducer<span class="token punctuation">;</span> </code></pre> <p>reducer中的initialState也需要初始化成immutable类型, 比如一个counter的reducer</p> <pre><code class="prism language-javascript"><span class="token keyword">import</span> <span class="token punctuation">{</span> Map <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'immutable'</span> <span class="token keyword">import</span> ActionTypes <span class="token keyword">from</span> <span class="token string">'../actions'</span> <span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token function">Map</span><span class="token punctuation">(</span><span class="token punctuation">{</span> count<span class="token operator">:</span> <span class="token number">0</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">(</span><span class="token parameter">state <span class="token operator">=</span> initialState<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">switch</span> <span class="token punctuation">(</span>action<span class="token punctuation">.</span>type<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">case</span> ActionTypes<span class="token punctuation">.</span><span class="token constant">INCREAMENT</span><span class="token operator">:</span> <span class="token keyword">return</span> state<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'count'</span><span class="token punctuation">,</span> state<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'count'</span><span class="token punctuation">)</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// 使用set或setIn来更改值, get或者getIn来取值</span> <span class="token keyword">case</span> ActionTypes<span class="token punctuation">.</span><span class="token constant">DECREAMENT</span><span class="token operator">:</span> <span class="token keyword">return</span> state<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">'count'</span><span class="token punctuation">,</span> state<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'count'</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token keyword">return</span> state <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> <p>state成为了immutable类型,connect的mapStateToProp也需要相应的改变</p> <pre><code class="prism language-javascript"><span class="token keyword">const</span> <span class="token function-variable function">mapStateToProps</span> <span class="token operator">=</span> <span class="token parameter">state</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span> count<span class="token operator">:</span> state<span class="token punctuation">.</span><span class="token function">getIn</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'counter'</span><span class="token punctuation">,</span> <span class="token string">'count'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">// 永远不要在mapStateToProps里使用`toJS`方法,因为它永远返回一个新的对象</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> </code></pre> <p>在shouldComponentUpdate里就可以使用immutable.is或者instance.equals来进行数据的对比了。</p> <h3>Mobx</h3> <p>Mobx是一个功能强大,上手非常容易的状态管理工具。redux的作者也曾经向大家推荐过它,在不少情况下可以使用Mobx来替代掉redux。<br> 这张图来自于官网,把这张图理解清楚了。基本上对于mobx的理解就算入门了。<br> 官网有明确的核心概念使用方法,并配有egghead的视频教程。这里就不一一赘述了。<br> 要特别注意当使用 mobx-react 时可以定义一个新的生命周期钩子函数 componentWillReact。当组件因为它观察的数据发生了改变,它会安排重新渲染,这个时候 componentWillReact 会被触发。这使得它很容易追溯渲染并找到导致渲染的操作(action)。</p> <ul> <li>componentWillReact 不接收参数</li> <li>componentWillReact 初始化渲染前不会触发 (使用componentWillMount 替代)</li> <li>componentWillReact 对于 mobx-react@4+, 当接收新的props 时并在 setState 调用后会触发此钩子</li> <li>要触发componentWillReact必须在render里面用到被观察的变量</li> <li>使用Mobx之后不会触发componentWillReceiveProps</li> </ul> </div> </div> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1598678357019492352"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(javascript,react.js,前端)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1830496529589301248.htm" title="前端Vue + qrcode实现二维码生成" target="_blank">前端Vue + qrcode实现二维码生成</a> <span class="text-muted">小倪有点菜</span> <a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>后端接口会返回一串由数字和英文组合的字符串getQRInviteCode(){//清除上一次的二维码if(this.$refs.qrcode){this.$refs.qrcode.innerHTML='';//清除二维码方法}//生成二维码(这里有个坑,一定要在new关键字前面用等于号,赋给一个变量,否则vue运行会报错)qrcode是HTML中的显示二维码的divsetTimeout(()=>{</div> </li> <li><a href="/article/1830481530271657984.htm" title="web零碎知识" target="_blank">web零碎知识</a> <span class="text-muted">白色的风扇</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>在后端想要发送一个JSON对象可以使用Gson//使用Gson将对象转换为JSON字符串Gsongson=newGson();Stringjson=gson.toJson(user);就会把一个对象转化为一个JSON字符串,//设置响应内容类型为JSONresponse.setContentType("application/json");这样返回前端的时候就会将JSON字符串转化为一个JSON对</div> </li> <li><a href="/article/1830474601877041152.htm" title="cornerstonejs介绍" target="_blank">cornerstonejs介绍</a> <span class="text-muted">花花进修</span> <a class="tag" taget="_blank" href="/search/DICOM%E5%8C%BB%E5%AD%A6%E5%BD%B1%E5%83%8F%E6%9F%A5%E7%9C%8B%E5%99%A8/1.htm">DICOM医学影像查看器</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/npm/1.htm">npm</a><a class="tag" taget="_blank" href="/search/yarn/1.htm">yarn</a> <div>Cornerstone.js是一个用于医疗成像应用程序的开源JavaScript库。它专门设计用于在Web浏览器中处理和显示DICOM(数字成像和通信在医学领域)图像。Cornerstone.js为开发者提供了强大的工具,可以轻松构建功能丰富的医学图像查看器,广泛应用于放射学、病理学、超声成像等领域。特点高性能图像渲染:支持大尺寸医学图像的快速渲染,包括CT扫描、MRI、X光片等。利用GPU加速(</div> </li> <li><a href="/article/1830456405056909312.htm" title="h5在ios qq浏览器打开图片不显示" target="_blank">h5在ios qq浏览器打开图片不显示</a> <span class="text-muted">O蚂蚁O</span> <div>把图片链接改变成https即可:纯前端实现代码:1、在vue项目的main.js添加过滤器://图片过滤Vue.filter('imgHost',function(value){varimgStrArr=value.split("?");//console.log(imgStrArr[0]);varhttpHead=imgStrArr[0].split(":");if(httpHead[0]=="</div> </li> <li><a href="/article/1830454932680044544.htm" title="WordPress 后台缓存插件:WP Admin Cache提高缓存页面" target="_blank">WordPress 后台缓存插件:WP Admin Cache提高缓存页面</a> <span class="text-muted">818源码资源站</span> <a class="tag" taget="_blank" href="/search/%E6%BA%90%E7%A0%81%E4%B8%8B%E8%BD%BD00818.cn/1.htm">源码下载00818.cn</a><a class="tag" taget="_blank" href="/search/%E6%BA%90%E7%A0%81%E4%B8%8B%E8%BD%BD818%E8%B5%84%E6%BA%90%E7%AB%99/1.htm">源码下载818资源站</a><a class="tag" taget="_blank" href="/search/%E7%BC%93%E5%AD%98/1.htm">缓存</a> <div>使用WordPress建站会安装一些静态缓存插件,比如:WPRocket、CacheEnabler、CometCache、W3TotalCache、WPSuperCache、WPFastestCache、HyperCache等等,这些都用于缓存前端。今天介绍一款专门用于缓存后台的插件:WPAdminCache。启用后,提速效果还是很明显,比如后台所有文章页面秒开。缓存会在更新文章、保存设置、保存小</div> </li> <li><a href="/article/1830454050815045632.htm" title="加密与安全_前后端通过AES-CBC模式安全传输数据" target="_blank">加密与安全_前后端通过AES-CBC模式安全传输数据</a> <span class="text-muted">小小工匠</span> <a class="tag" taget="_blank" href="/search/%E3%80%90%E5%8A%A0%E5%AF%86%E4%B8%8E%E5%AE%89%E5%85%A8%E3%80%91/1.htm">【加密与安全】</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a><a class="tag" taget="_blank" href="/search/AES-CBC/1.htm">AES-CBC</a> <div>文章目录Pre概述前端加密是否有意义?环境准备加密方法、MODE和PADDING的选择前端后端应用:从传输到解密的全过程安全性增强动态生成密钥和初始向量1.前端:动态生成密钥和IV2.后端:解密动态密钥和IV结语Pre加密与安全_解密AES加密中的IV和Seed加密与安全_双向RSA+AES加密及Code实现加密与安全_常见的分组密码ECB、CBC、CFB、OFB模式介绍概述当我们在前端和后端之间</div> </li> <li><a href="/article/1830452036005621760.htm" title="nginx部署前端vue项目" target="_blank">nginx部署前端vue项目</a> <span class="text-muted">iangyu</span> <a class="tag" taget="_blank" href="/search/%E8%BF%90%E7%BB%B4/1.htm">运维</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>在Nginx上部署Vue.js前端项目相对简单,通常包括以下几个步骤:1.构建Vue.js项目首先,你需要将Vue.js项目打包为静态文件。npmrunbuild这将生成一个dist文件夹,里面包含了你的Vue.js应用的所有静态资源。2.安装Nginx在服务器上安装Nginx。如果你使用的是Ubuntu,可以使用以下命令安装:sudoaptupdatesudoaptinstallnginx3.配</div> </li> <li><a href="/article/1830448280153190400.htm" title="javascript模板" target="_blank">javascript模板</a> <span class="text-muted">wanggs</span> <div>模板DocumentClick{{title}}{{content}}$(function(){$("#btn").click(function(){varhtml=$("#template").html();html=html.replace("{{id}}",Math.random());html=html.replace("{{title}}","Hello,"+newDate().getT</div> </li> <li><a href="/article/1830443466828640256.htm" title="javascript网页设计案例" target="_blank">javascript网页设计案例</a> <span class="text-muted">Min_nna</span> <a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/jquery%E5%8A%9F%E8%83%BD/1.htm">jquery功能</a><a class="tag" taget="_blank" href="/search/ai%E5%88%86%E6%9E%90/1.htm">ai分析</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>以下是一些使用JavaScript进行网页设计的案例,这些案例展示了JavaScript在前端开发中的强大功能和灵活性。每个案例都包含了基本的实现思路和代码示例。图片画廊(ImageGallery)功能:展示一组图片,并支持点击放大查看。实现思路:使用HTML和CSS创建图片网格。使用JavaScript处理图片点击事件,显示放大的图片。代码示例:ImageGallery×consti</div> </li> <li><a href="/article/1830434639743905792.htm" title="Nginx部署前端Vue项目" target="_blank">Nginx部署前端Vue项目</a> <span class="text-muted">hai40587</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a> <div>在使用Nginx部署前端Vue项目时,我们主要关注的是如何高效地将静态资源(HTML、CSS、JavaScript、图片等)提供给客户端浏览器。Vue.js是一个流行的JavaScript框架,用于构建用户界面,而Nginx作为一个高性能的HTTP和反向代理服务器,非常适合用于静态资源的托管。以下将详细介绍如何使用Nginx部署Vue项目,包括环境准备、Vue项目构建、Nginx配置、部署过程以及</div> </li> <li><a href="/article/1830419013977600000.htm" title="使用 Nginx 部署前端 Vue 项目" target="_blank">使用 Nginx 部署前端 Vue 项目</a> <span class="text-muted">vvvae1234</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>在这篇文章中,我们将深入探讨如何使用Nginx部署一个Vue.js前端项目。Vue是一个流行的前端JavaScript框架,而Nginx则是一个性能卓越的Web服务器和反向代理服务器。通过将这两者结合起来,我们可以高效地托管我们的前端应用。一、环境准备在开始部署之前,我们需要确保我们的环境中已安装以下软件:Node.js和npm:用于构建Vue项目。VueCLI:用于快速创建Vue项目。Nginx</div> </li> <li><a href="/article/1830415106148757504.htm" title="jQuery实现前端下载功能" target="_blank">jQuery实现前端下载功能</a> <span class="text-muted">天农学子</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>js实现前端下载功能前端代码html代码导出明细js代码functionexportExcel(){//定义要发送的参数letpostData=$("#searchForm").serializeObject();//发送POST请求fetch('${ctxPO}/url/PosInvoiceUrlController/exportPosInvoice',{method:'POST',body:J</div> </li> <li><a href="/article/1830409935008133120.htm" title="使用Nginx部署前端Vue项目" target="_blank">使用Nginx部署前端Vue项目</a> <span class="text-muted">bigbig猩猩</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/nginx/1.htm">nginx</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a> <div>在使用Nginx部署前端Vue项目时,我们主要关注的是如何高效地将静态资源(HTML、CSS、JavaScript、图片等)提供给客户端浏览器。Vue.js是一个流行的JavaScript框架,用于构建用户界面,而Nginx作为一个高性能的HTTP和反向代理服务器,非常适合用于静态资源的托管。以下将详细介绍如何使用Nginx部署Vue项目,包括环境准备、Vue项目构建、Nginx配置、部署过程以及</div> </li> <li><a href="/article/1830405769846157312.htm" title="Easyui Datagrid实现行操作" target="_blank">Easyui Datagrid实现行操作</a> <span class="text-muted">天农学子</span> <a class="tag" taget="_blank" href="/search/easyui/1.htm">easyui</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a> <div>EasyuiDatagrid实现行操作效果分析实现此功能需要实现2点1、首列的内容全部需要渲染成申请开票2、点击申请开票可以获获取到指定的行内容,在执行后续操作实现方案1、首行格式化,在table的th属性中加入formatter示例代码如下操作2、在JavaScript中编写代码formatOperatefunctionformatOperate(val,row){return'申请开票';}当</div> </li> <li><a href="/article/1830399088420548608.htm" title="前端框架与库的区别:深入解析与实战指南" target="_blank">前端框架与库的区别:深入解析与实战指南</a> <span class="text-muted">DTcode7</span> <a class="tag" taget="_blank" href="/search/HTML%E7%BD%91%E7%AB%99%E5%BC%80%E5%8F%91/1.htm">HTML网站开发</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%E4%B9%8Bhtml/1.htm">前端基础入门三大核心之html</a><a class="tag" taget="_blank" href="/search/HTML/1.htm">HTML</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/web/1.htm">web</a><a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/H5/1.htm">H5</a> <div>前端框架与库的区别:深入解析与实战指南基本概念和作用框架库功能使用思路与代码示例示例一:使用React框架构建组件示例二:使用Lodash库进行数据处理示例三:使用Vue.js框架进行双向数据绑定实际工作中的使用技巧经验分享自行拓展内容在前端开发领域,框架(Framework)和库(Library)是两个经常被提及但又容易混淆的概念。它们都是构建Web应用程序的重要工具,但各自拥有不同的设计哲学和</div> </li> <li><a href="/article/1830399087422304256.htm" title="前端开发中的单元测试与端到端测试:全面解析与实战指南" target="_blank">前端开发中的单元测试与端到端测试:全面解析与实战指南</a> <span class="text-muted">DTcode7</span> <a class="tag" taget="_blank" href="/search/HTML%E7%BD%91%E7%AB%99%E5%BC%80%E5%8F%91/1.htm">HTML网站开发</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%E4%B9%8Bhtml/1.htm">前端基础入门三大核心之html</a><a class="tag" taget="_blank" href="/search/HTML/1.htm">HTML</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/web/1.htm">web</a><a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/H5/1.htm">H5</a> <div>前端开发中的单元测试与端到端测试:全面解析与实战指南引言单元测试:基础与实践基本概念目的与优势实战演练示例一:加法功能单元测试扩展视角端到端测试:场景与执行基本概念目的与优势实战演练示例二:登录流程端到端测试扩展视角结合经验的技巧分享引言在现代前端开发中,测试是保证代码质量和维护系统稳定性不可或缺的一环。单元测试(unittesting)与端到端测试(end-to-endtesting)是两种常用</div> </li> <li><a href="/article/1830398960100012032.htm" title="前端基础入门三大核心之HTML篇:深入解析PNG8、PNG16、PNG24与PNG32的差异及网页应用指南" target="_blank">前端基础入门三大核心之HTML篇:深入解析PNG8、PNG16、PNG24与PNG32的差异及网页应用指南</a> <span class="text-muted">DTcode7</span> <a class="tag" taget="_blank" href="/search/HTML%E7%BD%91%E7%AB%99%E5%BC%80%E5%8F%91/1.htm">HTML网站开发</a><a class="tag" taget="_blank" href="/search/%23/1.htm">#</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83%E4%B9%8Bhtml/1.htm">前端基础入门三大核心之html</a><a class="tag" taget="_blank" href="/search/HTML5/1.htm">HTML5</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/web/1.htm">web</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E4%B8%89%E5%A4%A7%E6%A0%B8%E5%BF%83/1.htm">前端三大核心</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E5%BC%80%E5%8F%91/1.htm">网页开发</a> <div>前端基础入门三大核心之HTML篇:深入解析PNG8、PNG16、PNG24与PNG32的差异及网页应用指南基础概念与作用说明PNG8PNG16PNG24PNG32代码示例与使用场景PNG8示例PNG24示例PNG32示例性能优化与最佳实践防范漏洞提示结语与讨论在网页设计与前端开发中,选择合适的图像格式是至关重要的一步,它直接关系到页面加载速度、视觉效果乃至用户体验。PNG作为一种广泛应用的图像格式</div> </li> <li><a href="/article/1830391397795065856.htm" title="SpringBoot项目集成数据脱敏(密码加密)功能" target="_blank">SpringBoot项目集成数据脱敏(密码加密)功能</a> <span class="text-muted">明明在干嘛</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E8%84%B1%E6%95%8F/1.htm">数据脱敏</a><a class="tag" taget="_blank" href="/search/jasypt/1.htm">jasypt</a><a class="tag" taget="_blank" href="/search/AES/1.htm">AES</a> <div>代码连接【https://gitee.com/pengmqqq/sensitive-data-encryption】介绍后端敏感数据加密的一些解决方案,包括:配置文件敏感数据加解密前端传输敏感数据加解密数据库获取的敏感数据加解密软件架构配置文件数据脱敏:Jasypt+AES前后端传输以及数据库存储数据脱敏:AOP+AES使用说明配置文件数据脱敏将需要脱敏的数据进行加密之后再放入配置文件(注意要使用</div> </li> <li><a href="/article/1830350556338679808.htm" title="如何设置element ui选择结束时间为23:59:59?" target="_blank">如何设置element ui选择结束时间为23:59:59?</a> <span class="text-muted">weixin_42220130</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/element/1.htm">element</a><a class="tag" taget="_blank" href="/search/ui/1.htm">ui</a><a class="tag" taget="_blank" href="/search/%E6%97%B6%E9%97%B4/1.htm">时间</a><a class="tag" taget="_blank" href="/search/%E7%BB%93%E6%9D%9F/1.htm">结束</a> <div>两个方法,不过都是针对于传值给后端做的处理,不包括前端展示1每次发送请求时更改结束时间给后端//请求函数getDataList(){this.dataListLoading=true;//请求参数手动更改if(this.searchForm.timeArray.length===2&&this.searchForm.timeArray[1]!==""){this.searchForm.timeAr</div> </li> <li><a href="/article/1830340979626962944.htm" title="html语言及js脚本基础,Javascript基础学习笔记(菜鸟必看篇)" target="_blank">html语言及js脚本基础,Javascript基础学习笔记(菜鸟必看篇)</a> <span class="text-muted">游苏昱</span> <a class="tag" taget="_blank" href="/search/html%E8%AF%AD%E8%A8%80%E5%8F%8Ajs%E8%84%9A%E6%9C%AC%E5%9F%BA%E7%A1%80/1.htm">html语言及js脚本基础</a> <div>什么是变量?变量是用于存储信息的容器变量的声明语法:var变量名变量名=值;变量要先声明再赋值变量可以重复赋值变量的命名规则变量必须以字母开头;变量也能以$和_符号开头(不过我们不推荐这么做);变量名称对大小写敏感(a和A是不同的变量)。语句语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾。有个好的编码习惯,都要以;结尾数据类型在JavaScript中,一段信息就是一个值(value)。</div> </li> <li><a href="/article/1830336191975747584.htm" title="菜鸟笔记-001 如何用JavaScript脚本在文字中实现向左或向右插入空格" target="_blank">菜鸟笔记-001 如何用JavaScript脚本在文字中实现向左或向右插入空格</a> <span class="text-muted">胤祥矢量商铺</span> <a class="tag" taget="_blank" href="/search/%E8%8F%9C%E9%B8%9F%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/1.htm">菜鸟学习笔记</a><a class="tag" taget="_blank" href="/search/%E7%AC%94%E8%AE%B0/1.htm">笔记</a><a class="tag" taget="_blank" href="/search/illustrator/1.htm">illustrator</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E6%96%87%E5%AD%97%E6%93%8D%E4%BD%9C/1.htm">文字操作</a> <div>这是一个网友在线上问我的一个问题:如何用JavaScript脚本在文字中实现向左或向右插入空格下图是在文字左边插入了1/2个空格的效果:那么如何用javascript实现向左向右插入空格?其实这个功能,我在实际工作确实很少碰到,我只有祭出宝典查阅-IllustratorJavaScriptScriptingReference2022.pdf,当然你有更新版的更好。查到文字的向左插入空格或向左插入空</div> </li> <li><a href="/article/1830335056032395264.htm" title="this 关键字的绑定类型" target="_blank">this 关键字的绑定类型</a> <span class="text-muted">浮游本尊</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a> <div>在JavaScript中,理解this关键字的指向对于编写高质量的代码至关重要。this的指向取决于函数的调用方式,而不是定义方式。以下是几种常见的this绑定情形及其工作原理的解析。全局上下文中的this当在全局作用域中使用this或者函数在全局作用域被调用时,this通常指向全局对象。在Web浏览器中,这个全局对象是window,而在Node.js环境中则是global对象。functionc</div> </li> <li><a href="/article/1830296610773495808.htm" title="JavaScript 模块化开发:ES6 模块与 CommonJS 的对比与应用" target="_blank">JavaScript 模块化开发:ES6 模块与 CommonJS 的对比与应用</a> <span class="text-muted">程序员小羊!</span> <a class="tag" taget="_blank" href="/search/Java/1.htm">Java</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/es6/1.htm">es6</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a> <div>您好,我是程序员小羊!前言随着前端项目规模的增长,代码组织和管理变得越来越复杂。模块化开发成为解决这一问题的有效手段,能够帮助开发者将代码进行分割、复用和维护。JavaScript在发展过程中出现了多种模块化规范,其中最为广泛使用的有ES6模块(也称为ESModules)和CommonJS模块规范。本文将从原理、语法、应用场景和两者对比等多个方面深入探讨这两种模块化规范,帮助开发者更好地理解和应用</div> </li> <li><a href="/article/1830294718332891136.htm" title="【js逆向专题】4.python调用JS和扣代码" target="_blank">【js逆向专题】4.python调用JS和扣代码</a> <span class="text-muted">Regent Wan</span> <a class="tag" taget="_blank" href="/search/js%E9%80%86%E5%90%91/1.htm">js逆向</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/js%E9%80%86%E5%90%91/1.htm">js逆向</a> <div>小节目标:掌握python调用js代码方式熟悉js开放接口进行调用了解补环境的基本概念掌握js调试技巧一.pyexecjs的使用1.简介PyExecJS是一个Python库,用于在Python环境中执行JavaScript代码。它实际上是对ExecJS库的Python封装,ExecJS本身是一个通用的JavaScript运行环境的抽象层。使用PyExecJS,你可以在Python中执行JavaSc</div> </li> <li><a href="/article/1830291187236433920.htm" title="滴滴前端日常实习一面" target="_blank">滴滴前端日常实习一面</a> <span class="text-muted">真的很上进</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div>同步到csdn上一面水平居中、垂直居中的方法。align-item实现的是水平居中还是垂直居中。flex-direction为column的时候,是什么居中。js有什么数据类型。简单数据类型和复杂数据类型的区别深拷贝和浅拷贝的区别JSON.stringify有什么弊端怎么判断数组类型Vue3和Vue2的区别Vue生命周期钩子,activated和deactivated用过吗Vue里keep-ali</div> </li> <li><a href="/article/1830277707368329216.htm" title="js html css代码缩进,HTML/CSS/JS代码格式化" target="_blank">js html css代码缩进,HTML/CSS/JS代码格式化</a> <span class="text-muted">吃货喵</span> <a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/css%E4%BB%A3%E7%A0%81%E7%BC%A9%E8%BF%9B/1.htm">css代码缩进</a> <div>8种机械键盘轴体对比本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?我们在编辑器当中写代码的时候,可能因为编写时候不规范或者复制粘贴的操作导致代码格式混乱。我在之前采用的是JSFormat来格式化JavaScript和JSON,使用SublimeText自带的reindent命令格式化HTML和CSS的文件。基本上reindent命令就足够用了。但是有缺点,一些html文件的格式不够优美!</div> </li> <li><a href="/article/1830276699439329280.htm" title="【前端实例代码】使用HTML CSS 和 JavaScript制作一个五星评价的功能~可动态好评+差评+留言功能~" target="_blank">【前端实例代码】使用HTML CSS 和 JavaScript制作一个五星评价的功能~可动态好评+差评+留言功能~</a> <span class="text-muted">南北极之间</span> <a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E7%89%B9%E6%95%88%E6%BA%90%E7%A0%81/1.htm">web前端特效源码</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E5%85%A5%E9%97%A8/1.htm">编程入门</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1%E7%BC%96%E7%A8%8B%E5%85%A5%E9%97%A8%E4%BB%A3%E7%A0%81/1.htm">网页设计编程入门代码</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a> <div>bilibili在线视频演示地址:【web前端特效源码】使用HTMLCSS和JavaScript制作一个五星评价的功能!可动态好评+差评+留言功能!效果图:</div> </li> <li><a href="/article/1830276572196728832.htm" title="【前端实例代码】使用html+css+JavaScript实现带有波浪跳跃动画的登录表单页面" target="_blank">【前端实例代码】使用html+css+JavaScript实现带有波浪跳跃动画的登录表单页面</a> <span class="text-muted">南北极之间</span> <a class="tag" taget="_blank" href="/search/web%E5%89%8D%E7%AB%AF%E7%89%B9%E6%95%88%E6%BA%90%E7%A0%81/1.htm">web前端特效源码</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1%E4%BB%A3%E7%A0%81%E5%AE%9E%E4%BE%8B/1.htm">网页设计代码实例</a><a class="tag" taget="_blank" href="/search/css3/1.htm">css3</a> <div>效果图:完整代码:【前端实例代码】使用html+css+JavaScript实现带有波浪跳跃动画的登录表单页面@importurl("https://fonts.googleapis.com/css2?family=Muli&display=swap");*{box-sizing:border-box;</div> </li> <li><a href="/article/1830274807149719552.htm" title="基于Springboot和Vue的在线小说阅读平台系统(570)" target="_blank">基于Springboot和Vue的在线小说阅读平台系统(570)</a> <span class="text-muted">源码出售和定制</span> <a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a><a class="tag" taget="_blank" href="/search/%E5%90%8E%E7%AB%AF/1.htm">后端</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/1.htm">前端框架</a> <div>获取源码请滑到最底部访问官网项目配套调试视频和相对应的软件安装包1、项目描述具体请看视频演示2、项目开发工具开发工具:Idea或Eclipse数据库:MysqlJar包仓库:Maven前端框架:Vue2后端框架:Springboot3、项目图片4、演示视频基于Springboot和Vue的在线小说阅读平台系统(570)</div> </li> <li><a href="/article/1830274298179317760.htm" title="html5 css3 JavaScript响应式中文静态网页模板js源代码" target="_blank">html5 css3 JavaScript响应式中文静态网页模板js源代码</a> <span class="text-muted">Yucool01</span> <a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/css3/1.htm">css3</a> <div>该批次模板具备如下功能:首页,二级页面,三级页面登录页面均有,页面齐全,功能齐全,js+css+html,前端HTML纯静态页面,无后台,可用dreamweaver,sublime,webstorm等工具修改;部分网页模板效果图:有需要的同学可以下载学习一下:https://download.csdn.net/download/Yucool01/22408278https://download.c</div> </li> <li><a href="/article/25.htm" title="Java实现的简单双向Map,支持重复Value" target="_blank">Java实现的简单双向Map,支持重复Value</a> <span class="text-muted">superlxw1234</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/%E5%8F%8C%E5%90%91map/1.htm">双向map</a> <div>关键字:Java双向Map、DualHashBidiMap     有个需求,需要根据即时修改Map结构中的Value值,比如,将Map中所有value=V1的记录改成value=V2,key保持不变。   数据量比较大,遍历Map性能太差,这就需要根据Value先找到Key,然后去修改。   即:既要根据Key找Value,又要根据Value</div> </li> <li><a href="/article/152.htm" title="PL/SQL触发器基础及例子" target="_blank">PL/SQL触发器基础及例子</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/oracle%E6%95%B0%E6%8D%AE%E5%BA%93/1.htm">oracle数据库</a><a class="tag" taget="_blank" href="/search/%E8%A7%A6%E5%8F%91%E5%99%A8/1.htm">触发器</a><a class="tag" taget="_blank" href="/search/PL%2FSQL%E7%BC%96%E7%A8%8B/1.htm">PL/SQL编程</a> <div>  触发器的简介; 触发器的定义就是说某个条件成立的时候,触发器里面所定义的语句就会被自动的执行。因此触发器不需要人为的去调用,也不能调用。触发器和过程函数类似 过程函数必须要调用,   一个表中最多只能有12个触发器类型的,触发器和过程函数相似 触发器不需要调用直接执行, 触发时间:指明触发器何时执行,该值可取: before:表示在数据库动作之前触发</div> </li> <li><a href="/article/279.htm" title="[时空与探索]穿越时空的一些问题" target="_blank">[时空与探索]穿越时空的一些问题</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E9%97%AE%E9%A2%98/1.htm">问题</a> <div>       我们还没有进行过任何数学形式上的证明,仅仅是一个猜想.....       这个猜想就是; 任何有质量的物体(哪怕只有一微克)都不可能穿越时空,该物体强行穿越时空的时候,物体的质量会与时空粒子产生反应,物体会变成暗物质,也就是说,任何物体穿越时空会变成暗物质..(暗物质就我的理</div> </li> <li><a href="/article/406.htm" title="easy ui datagrid上移下移一行" target="_blank">easy ui datagrid上移下移一行</a> <span class="text-muted">商人shang</span> <a class="tag" taget="_blank" href="/search/js/1.htm">js</a><a class="tag" taget="_blank" href="/search/%E4%B8%8A%E7%A7%BB%E4%B8%8B%E7%A7%BB/1.htm">上移下移</a><a class="tag" taget="_blank" href="/search/easyui/1.htm">easyui</a><a class="tag" taget="_blank" href="/search/datagrid/1.htm">datagrid</a> <div>/** * 向上移动一行 * * @param dg * @param row */ function moveupRow(dg, row) { var datagrid = $(dg); var index = datagrid.datagrid("getRowIndex", row); if (isFirstRow(dg, row)) {</div> </li> <li><a href="/article/533.htm" title="Java反射" target="_blank">Java反射</a> <span class="text-muted">oloz</span> <a class="tag" taget="_blank" href="/search/%E5%8F%8D%E5%B0%84/1.htm">反射</a> <div>本人菜鸟,今天恰好有时间,写写博客,总结复习一下java反射方面的知识,欢迎大家探讨交流学习指教 首先看看java中的Class package demo; public class ClassTest { /*先了解java中的Class*/ public static void main(String[] args) { //任何一个类都</div> </li> <li><a href="/article/660.htm" title="springMVC 使用JSR-303 Validation验证" target="_blank">springMVC 使用JSR-303 Validation验证</a> <span class="text-muted">杨白白</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a> <div>JSR-303是一个数据验证的规范,但是spring并没有对其进行实现,Hibernate Validator是实现了这一规范的,通过此这个实现来讲SpringMVC对JSR-303的支持。 JSR-303的校验是基于注解的,首先要把这些注解标记在需要验证的实体类的属性上或是其对应的get方法上。 登录需要验证类 public class Login { @NotEmpty</div> </li> <li><a href="/article/787.htm" title="log4j" target="_blank">log4j</a> <span class="text-muted">香水浓</span> <a class="tag" taget="_blank" href="/search/log4j/1.htm">log4j</a> <div> log4j.rootCategory=DEBUG, STDOUT, DAILYFILE, HTML, DATABASE #log4j.rootCategory=DEBUG, STDOUT, DAILYFILE, ROLLINGFILE, HTML #console log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender log4</div> </li> <li><a href="/article/914.htm" title="使用ajax和history.pushState无刷新改变页面URL" target="_blank">使用ajax和history.pushState无刷新改变页面URL</a> <span class="text-muted">agevs</span> <a class="tag" taget="_blank" href="/search/jquery/1.htm">jquery</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a><a class="tag" taget="_blank" href="/search/Ajax/1.htm">Ajax</a><a class="tag" taget="_blank" href="/search/html5/1.htm">html5</a><a class="tag" taget="_blank" href="/search/chrome/1.htm">chrome</a> <div>表现 如果你使用chrome或者firefox等浏览器访问本博客、github.com、plus.google.com等网站时,细心的你会发现页面之间的点击是通过ajax异步请求的,同时页面的URL发生了了改变。并且能够很好的支持浏览器前进和后退。 是什么有这么强大的功能呢? HTML5里引用了新的API,history.pushState和history.replaceState,就是通过</div> </li> <li><a href="/article/1041.htm" title="centos中文乱码" target="_blank">centos中文乱码</a> <span class="text-muted">AILIKES</span> <a class="tag" taget="_blank" href="/search/centos/1.htm">centos</a><a class="tag" taget="_blank" href="/search/OS/1.htm">OS</a><a class="tag" taget="_blank" href="/search/ssh/1.htm">ssh</a> <div>一、CentOS系统访问 g.cn ,发现中文乱码。 于是用以前的方式:yum -y install fonts-chinese CentOS系统安装后,还是不能显示中文字体。我使用 gedit 编辑源码,其中文注释也为乱码。       后来,终于找到以下方法可以解决,需要两个中文支持的包: fonts-chinese-3.02-12.</div> </li> <li><a href="/article/1168.htm" title="触发器" target="_blank">触发器</a> <span class="text-muted">baalwolf</span> <a class="tag" taget="_blank" href="/search/%E8%A7%A6%E5%8F%91%E5%99%A8/1.htm">触发器</a> <div>触发器(trigger):监视某种情况,并触发某种操作。 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/before) 4.触发事件(insert/update/delete) 语法: create trigger triggerName after/before </div> </li> <li><a href="/article/1295.htm" title="JS正则表达式的i m g" target="_blank">JS正则表达式的i m g</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1.htm">正则表达式</a> <div>        g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即停止。         i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写。         m:表示</div> </li> <li><a href="/article/1422.htm" title="HTML5模式和Hashbang模式" target="_blank">HTML5模式和Hashbang模式</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/AngularJS/1.htm">AngularJS</a><a class="tag" taget="_blank" href="/search/Hashbang%E6%A8%A1%E5%BC%8F/1.htm">Hashbang模式</a><a class="tag" taget="_blank" href="/search/HTML5%E6%A8%A1%E5%BC%8F/1.htm">HTML5模式</a> <div>        我们可以用$locationProvider来配置$location服务(可以采用注入的方式,就像AngularJS中其他所有东西一样)。这里provider的两个参数很有意思,介绍如下。 html5Mode         一个布尔值,标识$location服务是否运行在HTML5模式下。 ha</div> </li> <li><a href="/article/1549.htm" title="[Maven学习笔记六]Maven生命周期" target="_blank">[Maven学习笔记六]Maven生命周期</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/maven/1.htm">maven</a> <div>从mvn test的输出开始说起   当我们在user-core中执行mvn test时,执行的输出如下:   /software/devsoftware/jdk1.7.0_55/bin/java -Dmaven.home=/software/devsoftware/apache-maven-3.2.1 -Dclassworlds.conf=/software/devs</div> </li> <li><a href="/article/1676.htm" title="【Hadoop七】基于Yarn的Hadoop Map Reduce容错" target="_blank">【Hadoop七】基于Yarn的Hadoop Map Reduce容错</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/hadoop/1.htm">hadoop</a> <div>运行于Yarn的Map Reduce作业,可能发生失败的点包括 Task Failure Application Master Failure Node Manager Failure Resource Manager Failure 1. Task Failure 任务执行过程中产生的异常和JVM的意外终止会汇报给Application Master。僵死的任务也会被A</div> </li> <li><a href="/article/1803.htm" title="记一次数据推送的异常解决端口解决" target="_blank">记一次数据推送的异常解决端口解决</a> <span class="text-muted">ronin47</span> <a class="tag" taget="_blank" href="/search/%E8%AE%B0%E4%B8%80%E6%AC%A1%E6%95%B0%E6%8D%AE%E6%8E%A8%E9%80%81%E7%9A%84%E5%BC%82%E5%B8%B8%E8%A7%A3%E5%86%B3/1.htm">记一次数据推送的异常解决</a> <div>   需求:从db获取数据然后推送到B         程序开发完成,上jboss,刚开始报了很多错,逐一解决,可最后显示连接不到数据库。机房的同事说可以ping 通。     自已画了个图,逐一排除,把linux 防火墙 和 setenforce 设置最低。    service iptables stop </div> </li> <li><a href="/article/1930.htm" title="巧用视错觉-UI更有趣" target="_blank">巧用视错觉-UI更有趣</a> <span class="text-muted">brotherlamp</span> <a class="tag" taget="_blank" href="/search/UI/1.htm">UI</a><a class="tag" taget="_blank" href="/search/ui%E8%A7%86%E9%A2%91/1.htm">ui视频</a><a class="tag" taget="_blank" href="/search/ui%E6%95%99%E7%A8%8B/1.htm">ui教程</a><a class="tag" taget="_blank" href="/search/ui%E8%87%AA%E5%AD%A6/1.htm">ui自学</a><a class="tag" taget="_blank" href="/search/ui%E8%B5%84%E6%96%99/1.htm">ui资料</a> <div>我们每个人在生活中都曾感受过视错觉(optical illusion)的魅力。 视错觉现象是双眼跟我们开的一个玩笑,而我们往往还心甘情愿地接受我们看到的假象。其实不止如此,视觉错现象的背后还有一个重要的科学原理——格式塔原理。 格式塔原理解释了人们如何以视觉方式感觉物体,以及图像的结构,视角,大小等要素是如何影响我们的视觉的。 在下面这篇文章中,我们首先会简单介绍一下格式塔原理中的基本概念,</div> </li> <li><a href="/article/2057.htm" title="线段树-poj1177-N个矩形求边长(离散化+扫描线)" target="_blank">线段树-poj1177-N个矩形求边长(离散化+扫描线)</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E7%BA%BF%E6%AE%B5%E6%A0%91/1.htm">线段树</a> <div>package com.ljn.base; import java.util.Arrays; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; /** * POJ 1177 (线段树+离散化+扫描线),题目链接为http://poj.org/problem?id=1177 </div> </li> <li><a href="/article/2184.htm" title="HTTP协议详解" target="_blank">HTTP协议详解</a> <span class="text-muted">chicony</span> <a class="tag" taget="_blank" href="/search/http%E5%8D%8F%E8%AE%AE/1.htm">http协议</a> <div>引言                                 </div> </li> <li><a href="/article/2311.htm" title="Scala设计模式" target="_blank">Scala设计模式</a> <span class="text-muted">chenchao051</span> <a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a><a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a> <div>Scala设计模式                我的话: 在国外网站上看到一篇文章,里面详细描述了很多设计模式,并且用Java及Scala两种语言描述,清晰的让我们看到各种常规的设计模式,在Scala中是如何在语言特性层面直接支持的。基于文章很nice,我利用今天的空闲时间将其翻译,希望大家能一起学习,讨论。翻译</div> </li> <li><a href="/article/2438.htm" title="安装mysql" target="_blank">安装mysql</a> <span class="text-muted">daizj</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E8%A3%85/1.htm">安装</a> <div>安装mysql   (1)删除linux上已经安装的mysql相关库信息。rpm  -e  xxxxxxx   --nodeps (强制删除)      执行命令rpm -qa |grep mysql 检查是否删除干净   (2)执行命令  rpm -i MySQL-server-5.5.31-2.el</div> </li> <li><a href="/article/2565.htm" title="HTTP状态码大全" target="_blank">HTTP状态码大全</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/http%E7%8A%B6%E6%80%81%E7%A0%81/1.htm">http状态码</a> <div>完整的 HTTP 1.1规范说明书来自于RFC 2616,你可以在http://www.talentdigger.cn/home/link.php?url=d3d3LnJmYy1lZGl0b3Iub3JnLw%3D%3D在线查阅。HTTP 1.1的状态码被标记为新特性,因为许多浏览器只支持 HTTP 1.0。你应只把状态码发送给支持 HTTP 1.1的客户端,支持协议版本可以通过调用request</div> </li> <li><a href="/article/2692.htm" title="asihttprequest上传图片" target="_blank">asihttprequest上传图片</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/ASIHTTPRequest/1.htm">ASIHTTPRequest</a> <div>NSURL *url =@"yourURL"; ASIFormDataRequest*currentRequest =[ASIFormDataRequest requestWithURL:url]; [currentRequest setPostFormat:ASIMultipartFormDataPostFormat];[currentRequest se</div> </li> <li><a href="/article/2819.htm" title="C语言中,关键字static的作用" target="_blank">C语言中,关键字static的作用</a> <span class="text-muted">e200702084</span> <a class="tag" taget="_blank" href="/search/C%2B%2B/1.htm">C++</a><a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/C%23/1.htm">C#</a> <div>在C语言中,关键字static有三个明显的作用: 1)在函数体,局部的static变量。生存期为程序的整个生命周期,(它存活多长时间);作用域却在函数体内(它在什么地方能被访问(空间))。 一个被声明为静态的变量在这一函数被调用过程中维持其值不变。因为它分配在静态存储区,函数调用结束后并不释放单元,但是在其它的作用域的无法访问。当再次调用这个函数时,这个局部的静态变量还存活,而且用在它的访</div> </li> <li><a href="/article/2946.htm" title="win7/8使用curl" target="_blank">win7/8使用curl</a> <span class="text-muted">geeksun</span> <a class="tag" taget="_blank" href="/search/win7/1.htm">win7</a> <div>1.  WIN7/8下要使用curl,需要下载curl-7.20.0-win64-ssl-sspi.zip和Win64OpenSSL_Light-1_0_2d.exe。 下载地址:  http://curl.haxx.se/download.html 请选择不带SSL的版本,否则还需要安装SSL的支持包   2.  可以给Windows增加c</div> </li> <li><a href="/article/3073.htm" title="Creating a Shared Repository; Users Sharing The Repository" target="_blank">Creating a Shared Repository; Users Sharing The Repository</a> <span class="text-muted">hongtoushizi</span> <a class="tag" taget="_blank" href="/search/git/1.htm">git</a> <div>转载自:   http://www.gitguys.com/topics/creating-a-shared-repository-users-sharing-the-repository/ Commands discussed in this section: git init –bare git clone git remote git pull git p</div> </li> <li><a href="/article/3200.htm" title="Java实现字符串反转的8种或9种方法" target="_blank">Java实现字符串反转的8种或9种方法</a> <span class="text-muted">Josh_Persistence</span> <a class="tag" taget="_blank" href="/search/%E5%BC%82%E6%88%96%E5%8F%8D%E8%BD%AC/1.htm">异或反转</a><a class="tag" taget="_blank" href="/search/%E9%80%92%E5%BD%92%E5%8F%8D%E8%BD%AC/1.htm">递归反转</a><a class="tag" taget="_blank" href="/search/%E4%BA%8C%E5%88%86%E4%BA%A4%E6%8D%A2%E5%8F%8D%E8%BD%AC/1.htm">二分交换反转</a><a class="tag" taget="_blank" href="/search/java%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8F%8D%E8%BD%AC/1.htm">java字符串反转</a><a class="tag" taget="_blank" href="/search/%E6%A0%88%E5%8F%8D%E8%BD%AC/1.htm">栈反转</a> <div>注:对于第7种使用异或的方式来实现字符串的反转,如果不太看得明白的,可以参照另一篇博客: http://josh-persistence.iteye.com/blog/2205768   /** * */ package com.wsheng.aggregator.algorithm.string; import java.util.Stack; /** </div> </li> <li><a href="/article/3327.htm" title="代码实现任意容量倒水问题" target="_blank">代码实现任意容量倒水问题</a> <span class="text-muted">home198979</span> <a class="tag" taget="_blank" href="/search/PHP/1.htm">PHP</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a><a class="tag" taget="_blank" href="/search/%E5%80%92%E6%B0%B4/1.htm">倒水</a> <div>形象化设计模式实战             HELLO!架构                     redis命令源码解析   倒水问题:有两个杯子,一个A升,一个B升,水有无限多,现要求利用这两杯子装C</div> </li> <li><a href="/article/3454.htm" title="Druid datasource" target="_blank">Druid datasource</a> <span class="text-muted">zhb8015</span> <a class="tag" taget="_blank" href="/search/druid/1.htm">druid</a> <div>推荐大家使用数据库连接池 DruidDataSource. http://code.alibabatech.com/wiki/display/Druid/DruidDataSource DruidDataSource经过阿里巴巴数百个应用一年多生产环境运行验证,稳定可靠。 它最重要的特点是:监控、扩展和性能。 下载和Maven配置看这里: http</div> </li> <li><a href="/article/3581.htm" title="两种启动监听器ApplicationListener和ServletContextListener" target="_blank">两种启动监听器ApplicationListener和ServletContextListener</a> <span class="text-muted">spjich</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/%E6%A1%86%E6%9E%B6/1.htm">框架</a> <div>引言:有时候需要在项目初始化的时候进行一系列工作,比如初始化一个线程池,初始化配置文件,初始化缓存等等,这时候就需要用到启动监听器,下面分别介绍一下两种常用的项目启动监听器   ServletContextListener  特点: 依赖于sevlet容器,需要配置web.xml 使用方法: public class StartListener implements </div> </li> <li><a href="/article/3708.htm" title="JavaScript Rounding Methods of the Math object" target="_blank">JavaScript Rounding Methods of the Math object</a> <span class="text-muted">何不笑</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/Math/1.htm">Math</a> <div>    The next group of methods has to do with rounding decimal values into integers. Three methods — Math.ceil(),  Math.floor(), and  Math.round() — handle rounding in differen</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>