共计 6419 个字符,预计需要花费 17 分钟才能阅读完成。
一、React 是什么
在 React 之前前端有三个里程碑意义的 library/framework
- jQuery 解决了浏览器兼容和 DOM 元素快捷操作问题,其链式操作 API 也对后续前端框架产生了深刻影响;
- Knockout 提出了前端代码 MVVM 分层理念,数据通过模板映射为 UI 视图,大幅度缩小了 DOM 操作;
- AngularJS 在 MVVM 根底上引入了双向绑定,数据变动主动反映到 UI,视图上的操作也反向自动更新数据;其通过指令拓展 HTML 的格调晋升了模板引擎的灵活性,惋惜作者引入了大量借鉴服务器编程的概念,让 AugularJS 学习老本直线回升,性能也略有有余;
React 是一个申明式、高效、灵便的用于构建用户界面的 JavaScript library,React 核心理念在于将一些简短、独立的代码片段组合成简单的 UI 界面,这些代码片段被称作“Component”。React 不是 MVC 框架,更像是其中 V,仅仅负责用户交互视图的渲染。
React 带来了三个颠覆性理念,在接下来的章节中将一一介绍:
- JSX,应用 JavaScript 表白 UI + 交互,充分利用 JavaScript 的灵活性;
- fx(props) = UI,数据驱动 UI,单向数据流、函数格调的页面组件;
- Virtual DOM,服务器、客户端应用同一套代码渲染——同构,解决前端利用 SEO 问题;
二、疾速初始化 React 我的项目
应用 Create React App [1] 能够疾速初始化一个 React Web 我的项目。
$ npx create-react-app learn-react --template typescript$ cd learn-react$ npm start
执行 npm start 后浏览器会在 http://localhost:3000 关上我的项目首页。
三、调试 React 利用
React 提供了 React Developer Tools[2],集成到了 Chrome Dev Tools,借此能够查看 React 组件树及其对应 Props、State。app.tsx
import React, {useState} from 'react';
function Button(props: { count: number}): JSX.Element {const [count, setCount] = useState(props.count); return (<button onClick={() => {setCount((c) => c + 1); }} > {count} </button> );}
function App() { const [count, setCount] = useState(0);
return (<div className="App"> <Button count={5} /> </div> );}
export default App;
index.tsx
import React from 'react';import * as ReactDOMClient from 'react-dom/client';
import App from './app';
const rootElement = document.querySelector('body') as Element;const root = ReactDOMClient.createRoot(rootElement);
root.render(<App />);
关上 Chrome Dev Tools 能够看到多了一个 Components 选项卡
四、Todo project
接下来边学习边做一个 Todo 我的项目体验一下 React。
五、应用 JSX 做更好的关注点拆散
在开始编写 React 程序之前须要理解一下 JSX。JSX 是 React 对 JavaScript 的语法拓展,用来在 JavaScript 文件内通过类 HTML 标签(HTML-like markup)表白页面的视图与交互逻辑。
<div className="container"> <CustomComponent onClick={() => {alert('Hello')}} > Hello {props.name}! </CustomComponent></div>
Web 页面由 HTML 内容、CSS 款式、JavaScript 交互形成,长期以来 Web 开发者将三者放在独立的文件中做拆散,这实际上是依照技术实现的拆散。
传统页面内容次要由 HTML 定义,JavaScript 逻辑是装点,随着古代网页交互性加强,页面内容很大水平是由 JavaScript 逻辑动静生成,同时渲染逻辑实质上与其余 UI 逻辑外在耦合,比方在 UI 中须要绑定处理事件、在某些时刻状态发生变化时须要告诉到 UI,以及须要在 UI 中展现筹备好的数据。
因而 React 应用 JSX 把渲染逻辑和 HTML 标签集成到一起。
这样开发者关注的不是 HTML 模板、JavaScript 渲染逻辑这样的技术实现,而是诸如 Sidebar、Form 这样的页面性能单元。
六、应用 JSX 编写 React 组件
返回 JSX 的函数就是 React 最简略的组件,能够和 HTML 标签一样嵌套应用。React 应用 props 参数向组件传递数据,晋升组件的复用性。
/** * JSX 语法隐式调用 React.createElement * 所以尽管代码中没有调用 React 的语句,依然须要引入 */import React from 'react';
interface IButton {/** 按钮展现文案 */ text: string; /** 点击按钮跳转链接 */ link?: string; /** 点击按钮自定义事件 */ onClick?: (event?: Event) => void}
function Button(props: IButton) {const { text, link, onClick} = props;
const redirectHandler = () => { location.href = link;};
return (<div className="button" onClick={onClick | redirectHandler} > {text} </div> );}
export default Button;
在应用组件时候,通过其标签的属性组装成 props 对象,传递给组件,语法和 HTML attribute 相似,但值能够是任意的 JavaScript 对象。
import React from 'react';
/** * 导入 ./button.tsx 中 export 的默认内容,命名为 Button 应用 * .tsx 拓展名能够省略 */import Button from './button';
interface IDialog {title: string; content: Element; showClose: boolean;}
function Dialog(props: IDialog) {const { title, content, showClose = false, children} = props;
const hideDialog = () => { // ...}
return (<div> <div className="dialog-title"> {title} </div> <div className="dialog-body"> {content | children} </div> {/* 没错,Button props 定义的属性,就是这样通过标签属性凋谢进去的 */} <Button title="勾销" onClick={hideDialog} /> <Button title="确认" onClick={() => {}} /> </div> );}
export default Dialog;
组件写好后通过 react-dom [3] 将组件渲染到页面。
import React from 'react';import ReactDOM from 'react-dom/client';import Dialog from './dialog';
// 把组件渲染到页面 id 为 root 的元素中 const rootElement = document.getElementById('root');const root = ReactDOM.createRoot(rootElement);root.render(<Dialog title="demo dialog" content="this is a dialog" showClose={false} />);
七、JSX 规定
React 组件有几个约定:
- 组件名称应用 Pascal 格调(首字母大写),以和 HTML 原生标签(div、p、a 等)辨别;
- 组件仅承受 props 一个参数,用来裸露组件可配置属性,其子组件被 React 通过 children 属性注入;
- 在组件外部 props 是只读的,不容许对其进行批改;
1. 必须有根节点
如同下面写的几个简略 demo,JSX 必须有 root 节点,即便多个同级元素没有父节点,也须要用虚构节点 <> 来包裹。
{/* 非法的 JSX */}<div id="box1"></div><div id="box2"></div>
{/* 非法的 JSX */}<> <div id="box1"></div> <div id="box2"></div></>
2. 所有标签须要闭合
在 HTML 中标签并不一定须要闭合。
<meta charset="UTF-8"><br><img src="https://g.alicdn.com/logo.png">
在 JSX 中能够混合 HTML 原生标签,但所有标签必须闭合。
<> <meta charset="UTF-8" /> <br/> <img src="https://g.alicdn.com/logo.png"/></>
3. 和 HTML 属性差别
- 在 React 中罕用的 DOM 个性和属性(包含事件处理)都应用小驼峰命名的形式,例如与 HTML 中的 tabindex 属性对应的 React 的属性是 tabIndex;
- HTML 局部属性名称与 JavaScript 保留字抵触,在 JSX 中须要应用代替名称;
- style 属性 value 是一个 CSS 属性组成的对象,为了让其合乎 JavaScript 语法规定,属性名应用驼峰命名(fontSize、backgroundColor),而不是 CSS 属性应用的连字符,这样能够很不便设置动静款式,但动态款式应该依赖 className 和 CSS 文件的配合;
function HelloWorldComponent(props) {const divStyle = { // 能够很不便设置动静款式 backgroundImage: 'url(' + props.imgUrl + ')', // 但动态款式应该尽量通过 className 设置类,通过 css file 解决 // 不举荐 color: 'blue' 这种动态款式间接在 JSX 的写法 color: 'blue', };
return (<div style={divStyle}> Hello World! </div> );}
- React 对于 Form 表单反对 defaultValue 属性,设置默认值,在运行时取值应用和 HTML 统一的 value 属性。
4. 主动本义 content
为了避免 XSS 攻打,JSX 会对间接设置的文本进行本义。
const content = ` 这里应该展现一张图片 <br> <img src="https://sc02.alicdn.com/kf/HTB1gUuPUkzoK1RjSZFl761i4VXaw.png" />`;<div> {content}</div>
页面成果:
在安全性有保障的时候,能够通过 dangerouslySetInnerHTML 禁用本义成果,展现 raw HTML
const content = ` 这里应该展现一张图片 <br> <img src="https://sc02.alicdn.com/kf/HTB1gUuPUkzoK1RjSZFl761i4VXaw.png" /> `;<div dangerouslySetInnerHTML={{__html: content}}/>
八、在 JSX 中 TODO 应用 {} 反对 JavaScript 表达式
JSX 中应用 {} 包裹 JavaScript 表达式解决动静逻辑,属性 value、子元素都能够,最常见的几个用法:
- {变量名} 读取变量值,双层 {{}} 并不是非凡语法,而是 {对象} 的快捷写法
<div style={{color: 'red'}}></div>
// 等同于
const styleObj = {color: 'red'};<div style={styleObj}></div>
- 三元表达式解决 if-else(if-else 是语句,不是表达式)
- map 解决循环逻辑,批量生成元素
interface IStuff {name: string; sex: 'male' | 'female';} function App () { const list: Array<IStuff> = [ { name: 'Byron', sex: 'male'}, {name: 'Casper', sex: 'male'}, {name: 'Junice', sex: 'female'}, ]; return (<ul className="stuff-list"> { list.map(stuff => { // 生成多个 const { name, sex} = stuff; return ({ <li /* 理论编程 className 设置有更好的表达方式,这里仅 demo 三元表达式应用 */} className={sex === 'male' ? 'stuff-male' : 'stuff-female'} onClick={() => { alert(name) }} > // 读取变量值 {name} </li> ); }) } </ul> );}
JSX 中正文也须要应用 {} 包裹,但这种写法过于不不便,大部分编译工具都能够解决双斜线格调 // 正文
九、JSX 的背地
JSX 的返回值既不是 DOM 元素,也不是 HTML 字符串,而是对 DOM 的一个 JSON 形容,这就是 React Element:
<button id="9527" className="btn-primary"> <span style={{color: 'red'}}> This is a Button </span></button>
JSX 用相似这样的构造表白:
{"type": "button", "props": { "id": "9527", "className": "btn-primary", "children": [ { "type": "span", "props": { "style": { "color": "red"}, "children": "This is a Button" } } ] }}
编译后理论是这样的调用:
React.createElement("button", { id: "9527", className: "btn-primary"},React.createElement("span", { style: { color: 'red'}}, "This is a Button"));
React.createElement(type, props, …children),上文提到过 React 会主动把 children 注入到 props,就是在这个过程。
理解了 JSX 之后能够开始编写动态的 React Component 了。残缺教程见语雀:https://www.yuque.com/sunluyong/fe4java/pwsehvspthh6gtrd
参考链接:
[1]https://create-react-app.dev/
[2]https://chrome.google.com/webstore/detail/react-developer-too…
[3]https://www.npmjs.com/package/react-dom
作者|谦行
点击立刻收费试用云产品 开启云上实际之旅!
原文链接
本文为阿里云原创内容,未经容许不得转载。