大家好,我是前端西瓜哥。
react.js 是被广泛使用的用于构建用户界面的 JS 库。下面给大家介绍一下学习 React 需要了解的一些概念。
在 React 这类框架流行之前,我们更新 UI,都是命令式的:我们需要手动指定元素,然后命令它改变样式。
// 纯 JS 写法
document.querySelector('#content') = '前端西瓜哥';
// jquery 写法
$('#content').text('content');
这种写法其实是相当繁琐的。你可能需要给元素加上 id,加上 class 作以区分,可能还需通过查找当前元素的父元素来界定区域,然后手动作添加子元素、进行修改样式、移除等操作。
所有的事情,都要自己一个个去操作,事无巨细,容易写错。
React 和 vue 这类框架的出现,让实际项目开发中命令式的写法成为了历史(只是偶尔还是会用到一点命令式写法)。
React 的编码是 声明式 的,你只需要维护好状态,然后在必要的时候通知 React,React 会自动帮你将 UI 渲染好。
class Compoent extends React.Component {
state = { content: '前端西瓜哥' };
updateContent = () => {
this.setState({ content: 'fe_watermelon' });
};
render() {
return (
<div>
<div>{this.state.content}</div>
<button onClick={() => this.updateContent()}>更新 content</button>
</div>
);
}
}
// 渲染为
// <div>前端西瓜哥</div>
React 中用 state 对象来保存可能会发生变化的状态,然后在 html 中用 {变量} 的方式嵌入,并通过 setState() 方法来更新状态,并重新渲染 UI。
UI = f(data)
数据映射到 UI 的操作过程,全部交给 React 做了,再也不用担心自己手写的 dom 更新写错了。你要做的只是更新状态,以及设置好状态在 HTML 中渲染的地方。
这种修改好状态,然后调用方法更新 UI 的做法,其实挺像做小游戏的。比如我们要做一个俄罗斯方块,当发生动作时,我们要更新好每个像素的位置(更新数据),然后调用自己实现的 render 方法,先清空画布,然后一个个绘制出来(映射 UI)。
组件化是什么?其实就是将模板、样式、脚本组合起来,成为一个组件。我们编写好一个个小的组件,然后将组件组合起来,就组成了我们的 UI 界面。
要想构建复杂的应用,合适的抽象是很重要的。对于 UI 来说,一种比较正确的思路,是将 UI 的分割成各个部分,我们只需要专注于一个职责专一的组件上,完成它后,再和其他的组件联合在一起,一点点构建出复杂的应用。
比如一个待办功能,我们可以抽象成下面这个样子。
<TodoContainer>
<TodoInput />
<TodoList />
</TodoContainer>
为了高效地更新 DOM,React 的底层使用了虚拟 DOM 来表示真实的 DOM 结构。
没有使用真实 DOM,是因为真实 DOM 对象比较复杂,有非常多的属性,比较占内存,所以抽象了一层 虚拟 DOM,此外还能附带上组件节点。
当状态更新时,会对比新旧虚拟 DOM 树得到补丁,通过打补丁的方式去更新真实 DOM 树。
React 中新旧 DOM 对比算法做了优化,要比普通的树比较算法要高效,这是 React 能被运用到实际生产环境的一个重要原因。
得益于 React 中虚拟 DOM 的实现,React 支持通过 React Native 编译为其他平台语言,来构建移动原生应用,比如 Andorid 或 iOS 原生应用。
虚拟 DOM 其实是真正 DOM 的一层抽象,这个抽象和平台无关,因此我们可以根据这层抽象去做跨平台的实现,让一套代码得以运行在不同平台。
但虚拟 DOM 并不能涵盖不同平台一些特有的 api,所以你其实还是要懂一些原生 APP 的知识的,对一些情况做特殊处理。
但至少,React 提供了一种跨平台的方案。
React 首先是一个 JS 库,它的语法不能跳脱 JS 的语法。在 JS 环境中,React 通过 React.crreatElement 来描述 DOM。
创建一个内容为 this.state.content 的 div 元素,我们需要这样写。
const el = React.createElement('div', {}, this.state.content);
第一个是 HTML 元素名或组件名,第二个是属性,第三个是子元素或子组件。
只是描述的一个 DOM 元素还算简单,但我们的页面是由复杂的 DOM 元素组织而成的,如果用上面这种写法,代码容易出错,也不方便进行维护。
于是 React 推出了 JSX,全称为 JavaScript Syntax Extension,即 JS 语法的扩展增强。通过 JSX,我们就可以实现 “在 JS 中写 HTML”。
const el = <div>{this.state.content}</div>;
但 JSX 还是不能被浏览器识别,需要编译为 JS。编译后,里面的这种 <div></div> 就会转换为使用了 React.createElement('div') 的代码。
React 要求数据从父组件通过 props 流向子组件,这样就能更好地定位组件中的某个数据的来源。
当然我们还是可以通过额外传递一个可以修改父组件状态方法给子组件,通过它去更新传给子组件的数据。
这样就能实现双向的数据流,但它依旧是显式的,仍然有助于理解程序的运转流程。
React 支持通过类或函数的方式编写组件,分别称为 类组件 和 函数组件。
类组件可以创建对象,所以自身可以维护状态是理所当然的事情。
一般来说,函数组件是不支持状态的,因为它是一个函数,只会接收外部传入的数据,然后渲染,内部没办法保持状态,因为它不是对象,只是一个用完就结束的函数。
函数组件不能使用内部状态的这种情况,在 React 推出了 React Hooks 之后解决了。
const Compoent = () => {
const [content, setContent] = useState('前端西瓜哥');
return (
<div>
<div>{content}</div>
<button onClick={() => setContent('fe_watermelon')}>更新</button>
</div>
);
};
我们在函数组件内使用 useState() 就可以创建一个内部状态,且可以通过 setXxx() 进行更新。
我第一次看到 React Hooks,就觉得这简直就是魔法,惊为天人。
底层其实是用一个额外的有序列表保存好了每个状态,和函数组件进行了绑定。为了做到这点,React 要求 Hooks 必须在每次执行时,保证顺序相同。
React Hooks 的一个优点是,将逻辑的最小单元从组件,缩小为更细粒度的 hooks 的组合。这让我们编写组件更加灵活。
来源:https://www.toutiao.com/article/7106510066282463776/
如今的 Web 前端已被 React、Vue 和 Angular 三分天下,尽管现在的 jQuery 已不再那么流行,但 jQuery 的设计思想还是非常值得致敬和学习的,特别是 jQuery 的插件化。
受控组件与非受控组件在官网与国内网上的资料都不多,有些人觉得它可有可不有,也不在意。这恰恰显示React的威力,满足不同规模大小的工程需求。
一般在传统模式下,我们构建前端项目很简单。就是下载各种js文件,如JQuery、Echart等,直接放置在html静态文件。Webpack则是JavaScript中比较知名的打包工具。这两个构建工具构成了React应用快速搭建的基础。
Gatsby能快速的使用 React 生态系统来生成静态网站,可以结合React Component、Markdown 和服务端渲染来完成静态网站生成让他更强大。
React推出后,出于不同的原因先后出现三种定义react组件的方式,殊途同归;具体的三种方式:函数式定义的无状态组件、es5原生方式React.createClass定义的组件、es6形式的extends React.Component定义的组件
React主要思想是通过构建可复用组件来构建用户界面,每个组件都有自己的生命周期,它规定了组件的状态和方法需要在哪个阶段改变和执行。所谓组件就是有限状态机,,表示有限个状态以及在这些状态之间的转移和动作行为的模型。
React 相关的优化:使用 babel-react-optimize 对 React 代码进行优化,检查没有使用的库,去除 import 引用,按需打包所用的类库,比如 lodash 、echarts 等.Webpack 构建打包存在的问题两个方面:构建速度慢,打包后的文件体积过大
这篇文章主要介绍React Router定义路由之后如何传值,有关React和React Router 。react router中页面传值的三种方法:props.params、query、state
react 高阶组件简单的理解是:一个包装了另一个基础组件的组件。高阶组件的两种形式:属性代理(Props Proxy)、反向继承 (Inheritance Inversion)
React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!