React课堂笔记1

2023-05-20,,

一、概要

React是用于构建用户界面的MVVM框架。

React拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。认为它可能是将来Web开发的主流工具之一。

官网:https://zh-hans.reactjs.org/

源码:https://github.com/facebook/react

React新文档 :(https://beta.reactjs.org/)(开发中....)

二、React特点

2.1、声明式设计

react是面向数据编程,不需要直接去控制dom,你只要把数据操作好,react自己会去帮你操作dom,可以节省很多操作dom的代码。这就是声明式开发。

以声明式编写 UI,可以让你的代码更加可靠,且方便调试。(注:命令式需要你一步一步的写需要干什么的步骤,而声明式只需要告诉目的,应该做什么,但是不用指定怎么做)

2.2、组件化开发

通过 React 构建组件,使得代码更加容易得到复用和维护,能够很好的应用在大项目的开发中。

2.3、使用JSX语法

JSX (JavaScript XML) 是 JavaScript 语法的扩展。React 开发大部分使用 JSX 语法(在JSX中可以将HTML于JS混写)。

2.4、灵活

react所控制的dom就是id为root的dom,页面上的其他dom元素你页可以使用jq等其他框架 。可以和其他库并存。

2.5、使用虚拟DOM、高效

虚拟DOM其实质是一个JavaScript对象,当数据和状态发生了变化,都会被自动高效的同步到虚拟DOM中,最后再将仅变化的部分同步到DOM中(不需要整个DOM树重新渲染)。

2.6、单向数据流

react是单向数据流,父组件传递给子组件的数据,子组件能够使用,但是不能直接通过this.props修改。 这样让数据清晰代码容易维护。

1.原生JS操作DOM繁琐,效率低

2.使用JS直接操作DOM,浏览器会进行大量的重绘重排

3.原生JS没有组件化编码方案,代码复用低

三、React相关技术

React可以开发Web应用—ReactJs
React可以开发移动端—React-native
React Native 是一个使用JavaScript 和 React 来编写跨终端移动应用(Android 或 IOS)的一种解决方案
React可以开发VR应用—React 360
React 360是一个创建3D和VR用户交互的框架.构建在React的基础之上,React是一个简化复杂UI创建的库,React 360可以让你用相似的工具和概念在网页上创建沉浸式的360度的内容。其特点:

React 360 是一个用于构建VR全景360体验的网页应用框架,基于React

React 360 提供了一些控件,用于快速创建360度沉浸式的内容

跨平台,支持电脑、移动设备、VR设备

支持多种格式的全景视频

四、创建第一个程序

4.1、Web端

1、准备一个空文件夹,打开终端输入命令 npm init -y   下载 package.json文件。

在目录下创建一个index.html文件

2、实例中我们引入了三个库: react.development.min.js 、react-dom.development.min.js 和 babel.min.js

方法有两种,一种本地下载,在终端输入指令npm i react react-dom。第二种是直接搜索网上

3、编写代码

写一个<div id="app"></div>

 <script>

        // 参数一,h2表示标签的名称
// 参数二,{}表示节点中的属性如,{title:"Hello"}
// 参数三,表示子节点,可以是文本节点
// 1、创建虚拟DOM节点
let vNode = React.createElement("h2", { title: "Hello" }, "Hello React Web!"); // 2、找到根节点
let app = document.querySelector("#app"); // 3、创建根节点
let root = ReactDOM.createRoot(app); // 4、将虚拟DOM挂载到根节点上
root.render(vNode);
</script>  

运行结果

4.2、JSX

代码:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React案例2</title>
<style>
.purple {
color: blueviolet;
}
</style>
</head> <body>
<div id="app"></div>
<!-- 三个库,react核心库,提供与dom相关的功能,bable可以将es6代码转换es5代码 -->
<script src="https://cdn.staticfile.org/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdn.staticfile.org/react-dom/18.2.0/umd/react-dom.development.js"></script>
<script src="https://cdn.staticfile.org/babel-standalone/7.20.6/babel.min.js"></script>
<!-- 需要bable解析 -->
<script type="text/babel"> // 1、创建虚拟DOM节点 vnode, 对比:React.createElement("h2", { title: "Hello" }, "Hello React Web!");
let vNode = (
<div class="purple">
<h2 title="Hello" >Hello React JSX!</h2>
</div>
) // 2、创建根节点
let root = ReactDOM.createRoot(document.getElementById("app")); // 3、将虚拟DOM挂载到根节点上
root.render(vNode);
</script> </body> </html>

4.3、脚手架

1.使用 create-react-app 脚手架创建项目

npx create-react-app 项目名 或者 yarn create react-app 项目名(npx 是一个临时使用第三方模块的命令,会临时下载这个包,使用完毕就删除了)

npm和npx的区别

区别1.一个永久存在(npm),一个临时安装(npx),用完后删除

区别2.npx 会帮你执行依赖包里的二进制文件。也就是说 npx 会自动查找当前依赖包中的可执行文件,如果找不到,就会去环境变量里面的 PATH 里找。如果依然找不到,就会帮你安装!

区别3.npx可以执行文件,但是npm不可以

虽然在本地搭建环境要费一些时间,但是你可以选择自己喜欢的编辑器来完成开发。以下是具体步骤:

    确保你安装了较新版本的 Node.js。
    按照 Create React App 安装指南创建一个新的项目
npx create-react-app my-app

  3.删除掉新项目中 src/ 文件夹下的所有文件。

4.4、vite+react项目

使用vite创建项目比较快,文件少,根据提示第一个输入项目名称,第二个选择是React,第三个选择TypeScript。

4.5、官网四个demo案例

这四个案例使用组件完成。

main.tsx文件

import React from 'react'
import ReactDOM from 'react-dom/client'
import HelloMessage from './HelloMessage'
import MarkdownEditor from './MarkdownEditor'
import Timer from './Timer'
import TodoApp from './TodoApp' ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<HelloMessage name="Taylor" />
<Timer/>
<TodoApp></TodoApp>
<MarkdownEditor></MarkdownEditor> </React.StrictMode>
) 

组件HelloMessage.tsx文件

import React from 'react'

export default class HelloMessage extends React.Component<any> {
render() {
return <div>Hello {this.props.name}</div>;
}
}

组件 Timer.tsx

import React from 'react'

export default class Timer extends React.Component<any,any> {
interval: number | undefined;
constructor(props: any) {
super(props);
this.state = { seconds: 0 };
} tick() {
this.setState((state: { seconds: number; }) => ({
seconds: state.seconds + 1
}));
} componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
} componentWillUnmount() {
clearInterval(this.interval);
} render() {
return (
<div>
Seconds: {this.state.seconds}
</div>
);
}
}

 组件TodoApp.tsx文件

import React from 'react'

export default class TodoApp extends React.Component<any,any> {
constructor(props: any) {
super(props);
this.state = { items: [], text: '' };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
} render() {
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} />
<form onSubmit={this.handleSubmit}>
<label htmlFor="new-todo">
What needs to be done?
</label>
<input
id="new-todo"
onChange={this.handleChange}
value={this.state.text}
/>
<button>
Add #{this.state.items.length + 1}
</button>
</form>
</div>
);
} handleChange(e: { target: { value: any; }; }) {
this.setState({ text: e.target.value });
} handleSubmit(e: { preventDefault: () => void; }) {
e.preventDefault();
if (this.state.text.length === 0) {
return;
}
const newItem = {
text: this.state.text,
id: Date.now()
};
this.setState((state: { items: any[]; }) => ({
items: state.items.concat(newItem),
text: ''
}));
}
} class TodoList extends React.Component {
render() {
return (
<ul>
{this.props.items.map((item: { id: React.Key | null | undefined; text: string | number | boolean | React.ReactElement<any, string | React.JSXElementConstructor<any>> | React.ReactFragment | React.ReactPortal | null | undefined; }) => (
<li key={item.id}>{item.text}</li>
))}
</ul>
);
}
}

组件MarkdownEditor.tsx文件 

import React from 'react'
import { Remarkable } from 'remarkable';
export default class MarkdownEditor extends React.Component<any,any> {
md: any;
constructor(props: any) {
super(props);
this.md = new Remarkable();
this.handleChange = this.handleChange.bind(this);
this.state = { value: 'Hello, **world**!' };
} handleChange(e: { target: { value: any; }; }) {
this.setState({ value: e.target.value });
} getRawMarkup() {
return { __html: this.md.render(this.state.value) };
} render() {
return (
<div className="MarkdownEditor">
<h3>Input</h3>
<label htmlFor="markdown-content">
Enter some markdown
</label>
<textarea
id="markdown-content"
onChange={this.handleChange}
defaultValue={this.state.value}
/>
<h3>Output</h3>
<div
className="content"
dangerouslySetInnerHTML={this.getRawMarkup()}
/>
</div>
);
}
}

需要用到插件,添加依赖:npm install remarkable --save

五、安装插件

为以后的react项目做准备

5.1、安装React开发调试插件

    进入到【谷歌扩展程序】界面。在谷歌浏览器直接输入: chrome://extensions/   即可进去扩展程序界面。
    把 .crx 结尾的文件拖入浏览器即可。
    运行 react 项目,打开控制台,就可以看到了。

5.2、安装VSCode插件

React/Redux/React-Native snippets 代码模板/代码片段

每个插件都会在页面显示怎么使用,这个也不例外

点击查看细节用法

例子

rcc
import React, { Component } from 'react' export default class FileName extends Component {
render() {
return <div>$2</div>
}
}
rce
import React, { Component } from 'react' export class FileName extends Component {
render() {
return <div>$2</div>
}
} export default $1
rcep
import React, { Component } from 'react'
import PropTypes from 'prop-types' export class FileName extends Component {
static propTypes = {} render() {
return <div>$2</div>
}
} export default $1
rpc
import React, { PureComponent } from 'react' export default class FileName extends PureComponent {
render() {
return <div>$2</div>
}
}
rpcp
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' export default class FileName extends PureComponent {
static propTypes = {} render() {
return <div>$2</div>
}
}
rpce
import React, { PureComponent } from 'react'
import PropTypes from 'prop-types' export class FileName extends PureComponent {
static propTypes = {} render() {
return <div>$2</div>
}
} export default FileName
rccp
import React, { Component } from 'react'
import PropTypes from 'prop-types' export default class FileName extends Component {
static propTypes = {
$2: $3,
} render() {
return <div>$4</div>
}
}
rfcp
import React from 'react'
import PropTypes from 'prop-types' function $1(props) {
return <div>$0</div>
} $1.propTypes = {} export default $1
rfc
import React from 'react' export default function $1() {
return <div>$0</div>
}
rfce
import React from 'react' function $1() {
return <div>$0</div>
} export default $1
rafcp
import React from 'react'
import PropTypes from 'prop-types' const $1 = (props) => {
return <div>$0</div>
} $1.propTypes = {} export default $1
rafc
import React from 'react' export const $1 = () => {
return <div>$0</div>
}
rafce
import React from 'react' const $1 = () => {
return <div>$0</div>
} export default $1
rmc
import React, { memo } from 'react' export default memo(function $1() {
return <div>$0</div>
})
rmcp
import React, { memo } from 'react'
import PropTypes from 'prop-types' const $1 = memo(function $1(props) {
return <div>$0</div>
}) $1.propTypes = {} export default $1
rcredux
import React, { Component } from 'react'
import { connect } from 'react-redux' export class FileName extends Component {
render() {
return <div>$4</div>
}
} const mapStateToProps = (state) => ({}) const mapDispatchToProps = {} export default connect(mapStateToProps, mapDispatchToProps)(FileName)
rcreduxp
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux' export class FileName extends Component {
static propTypes = {
$2: $3,
} render() {
return <div>$4</div>
}
} const mapStateToProps = (state) => ({}) const mapDispatchToProps = {} export default connect(mapStateToProps, mapDispatchToProps)(FileName)
rfcredux
import React, { Component } from 'react'
import { connect } from 'react-redux' export const FileName = () => {
return <div>$4</div>
} const mapStateToProps = (state) => ({}) const mapDispatchToProps = {} export default connect(mapStateToProps, mapDispatchToProps)(FileName)
rfreduxp
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux' export const FileName = () => {
return <div>$4</div>
} FileName.propTypes = {
$2: $3,
} const mapStateToProps = (state) => ({}) const mapDispatchToProps = {} export default connect(mapStateToProps, mapDispatchToProps)(FileName)
reduxmap
const mapStateToProps = (state) => ({}) const mapDispatchToProps = {}
React Native Components
rnc
import React, { Component } from 'react'
import { Text, View } from 'react-native' export default class FileName extends Component {
render() {
return (
<View>
<Text> $2 </Text>
</View>
)
}
}
rnf
import React from 'react'
import { View, Text } from 'react-native' export default function $1() {
return (
<View>
<Text> $2 </Text>
</View>
)
}
rnfs
import React from 'react'
import { StyleSheet, View, Text } from 'react-native' export default function $1() {
return (
<View>
<Text> $2 </Text>
</View>
)
} const styles = StyleSheet.create({})
rnfe
import React from 'react'
import { View, Text } from 'react-native' const $1 = () => {
return (
<View>
<Text> $2 </Text>
</View>
)
} export default $1
rnfes
import React from 'react'
import { StyleSheet, View, Text } from 'react-native' const $1 = () => {
return (
<View>
<Text> $2 </Text>
</View>
)
} export default $1 const styles = StyleSheet.create({})
rncs
import React, { Component } from 'react'
import { Text, StyleSheet, View } from 'react-native' export default class FileName extends Component {
render() {
return (
<View>
<Text> $2 </Text>
</View>
)
}
} const styles = StyleSheet.create({})
rnce
import React, { Component } from 'react'
import { Text, View } from 'react-native' export class FileName extends Component {
render() {
return (
<View>
<Text> $2 </Text>
</View>
)
}
} export default $1
Others
cmmb
/**
|--------------------------------------------------
| $1
|--------------------------------------------------
*/
desc
describe('$1', () => {
$2
})
test
test('should $1', () => {
$2
})
tit
it('should $1', () => {
$2
})
stest
import React from 'react'
import renderer from 'react-test-renderer' import { $1 } from '../$1' describe('<$1 />', () => {
const defaultProps = {}
const wrapper = renderer.create(<$1 {...defaultProps} />) test('render', () => {
expect(wrapper).toMatchSnapshot()
})
})
srtest
import React from 'react'
import renderer from 'react-test-renderer'
import { Provider } from 'react-redux' import store from 'src/store'
import { $1 } from '../$1' describe('<$1 />', () => {
const defaultProps = {}
const wrapper = renderer.create(
<Provider store={store}>
<$1 {...defaultProps} />)
</Provider>,
) test('render', () => {
expect(wrapper).toMatchSnapshot()
})
})
sntest
import 'react-native'
import React from 'react'
import renderer from 'react-test-renderer' import $1 from '../$1' describe('<$1 />', () => {
const defaultProps = {} const wrapper = renderer.create(<$1 {...defaultProps} />) test('render', () => {
expect(wrapper).toMatchSnapshot()
})
})
snrtest
import 'react-native'
import React from 'react'
import renderer from 'react-test-renderer'
import { Provider } from 'react-redux' import store from 'src/store/configureStore'
import $1 from '../$1' describe('<$1 />', () => {
const defaultProps = {}
const wrapper = renderer.create(
<Provider store={store}>
<$1 {...defaultProps} />
</Provider>,
) test('render', () => {
expect(wrapper).toMatchSnapshot()
})
})
hocredux
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux' export const mapStateToProps = (state) => ({}) export const mapDispatchToProps = {} export const $1 = (WrappedComponent) => {
const hocComponent = ({ ...props }) => <WrappedComponent {...props} /> hocComponent.propTypes = {} return hocComponent
} export default (WrapperComponent) =>
connect(mapStateToProps, mapDispatchToProps)($1(WrapperComponent))
hoc
import React from 'react'
import PropTypes from 'prop-types' export default (WrappedComponent) => {
const hocComponent = ({ ...props }) => <WrappedComponent {...props} /> hocComponent.propTypes = {} return hocComponent
}

5.3、Simple React Snippets 更加简洁的代码片段

Snippet Renders
imr Import React
imrc Import React / Component
imrd Import ReactDOM
imrs Import React / useState
imrse Import React / useState useEffect
impt Import PropTypes
impc Import React / PureComponent
cc Class Component
ccc Class Component With Constructor
cpc Class Pure Component
ffc Function Component
sfc Stateless Function Component (Arrow function)
cdm componentDidMount
uef useEffect Hook
cwm componentWillMount
cwrp componentWillReceiveProps
gds getDerivedStateFromProps
scu shouldComponentUpdate
cwu componentWillUpdate
cdu componentDidUpdate
cwun componentWillUnmount
cdc componentDidCatch
gsbu getSnapshotBeforeUpdate
ss setState
ssf Functional setState
usf Declare a new state variable using State Hook
ren render
rprop Render Prop
hoc Higher Order Component
cp Context Provider
cpf Class Property Function

 

好了,第一节结束!

React课堂笔记1的相关教程结束。

《React课堂笔记1.doc》

下载本文的Word格式文档,以方便收藏与打印。