目录
跳转链接 => React_02 学习笔记
跳转链接 => React_03 学习笔记
跳转链接 => React_04 菜谱项目
跳转链接 => React_05 Hooks
目标
- 使用 render 方法渲染页面显示
- 了解 jsx 的 语法规则
- 使用 jsx 的 语法进行 界面渲染
- 能够使用 react 脚手架完成 react 项目构建
- 掌握 函数组件 和 类组件 的定义
- 能够给标签绑定事件
- 能够解决事件绑定中 this 指向问题
- 能够实现父子组件 传值
- 能够使用 state 进行数据读取与更新
- 能够对于 props 传入数据限制
- 能够设置好 props 的默认值
- 能够完成表单项数据的获取
一、React
网址:React – A JavaScript library for building user interfaces
1.1、概述
React 起源于 Facebook (脸书) 的内部项目,它是一个用于构建用户界面的 javascript 库,Facebook 用它来架设公司的 Instagram 网站,并于 2013年5月 开源。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。认为它可能是将来 Web 开发的主流工具之一。
1.2、特点
- 声明式
你只需要描述 UI 看起来是什么样式,就跟写 HTML 一样,React 负责渲染 UI,数据的声明
- 基于组件
组件是 React 最重要的内容,组件表示页面中的部分内容 -- react 元素 -- 虚拟 dom
- 学习一次,随处使用
使用 React 可以开发 Web 应用( React-dom ),使用 React 可以开发移动端( react-native ),可以开发 VR 应用( react 360 )
1.3、浏览器扩展与 vscode 开发扩展安装
Chrome 浏览器扩展:https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=zh-CN
VSCode 安装 React 开发扩展 : JS JSX Snippets
1.4、第一个 react 应用程序
react 开发需要引入多个依赖文件,其中 react.js、react-dom.js 这两个文件是我们创建 react 应用程序 必须 要引入的 依赖文件 。
react.js 是核心,提供创建元素,组件 等功能
https://unpkg.com/react@17/umd/react.development.js
react-dom.js 提供 DOM 相关功能
下载对应的 react.js 和 react-dom.js 的开发版本的 js 类库文件到本机中后,通过 script 引入到当前的网页中
// React 的 核心库
<script src="https://unpkg.com/react@17/umd/react.development.js"></script>
// DOM 相关的功能
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
在 html 中定义 react.js 渲染容器 id 和进行 React 实例化 相关操作, 完成 helloworld 显示
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>测试一下</title> </head> <body> <div id="app"></div> <script src="https://unpkg.com/react@17/umd/react.development.js"></script> <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <script> ReactDOM.render(React.createElement('div',{},'你好世界'),document.querySelector('#app')); </script> </body> </html>
<!-- 真实的 html 挂载点 --> <div id="root"></div> <script> // 使用创建虚拟 DOM 的方法 let el = React.createElement // 创建一个虚拟 DOM 对象 let vnode = el( 'div', null, el( 'ul', null, el('li', null, '第 1 个'), el('li', null, '第 2 个'), el('li', null, '第 3 个') ) ) // 把虚拟 DOM 挂载到真实的 DOM 节点中 ReactDOM.render(vnode, document.querySelector('#root')) </script>
二、JSX
2.1、简介
由于通过 React.createElement( ) 方法创建的 React 元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅,开发时写代码很不友好。
React 使用 JSX 来替代常规的 JavaScript,JSX 可以理解为是 JavaScript 的语法扩展 (也可理解为 JS 的 超集 ),它里面的标签申明要符合 XML 规范要求。
jsx 浏览器认识吗 ?
答:浏览器只能识别 js ,对于 jsx 不能识别。浏览如何来识别 jsx 呢 ?
答:react 工程化 中内置了一个将 jsx => js 的 编译 工具 => babel
xml 是什么 ?
答:严格的 标记性语言。
简单的理解,xml 当作是一个严格的 html 语言,属性名称不要有大写字母,属性值必须要用引号括起来
标签有开始就必须要有 结束 /
<div></div>
<img />
属性值 必须要有 引号 括起来
<img src="" alt="" />
React 不一定非要使用 JSX,但它有以下优点:
- JSX 执行更快,因为它在编译为 JavaScript 代码后进行了优化
jsx 是浏览不能够直接运行的,它需要一个 转译器 进行 转译( babel ), 转为 js
- 它是类型安全的,在编译过程中就能发现错误
- 声明式语法更加直观,与 HTML 结构相同,降低了学习成本,提升开发效率速度
- jsx 语法中 一定要有一个 顶级元素包裹 ,否则编译报错,程序不能运行
js != jsx jsx => js+xml 集合版本,js 增强版,js 有的它有,js 没有它也有
2.2、重构 helloworld
在项目中尝试 JSX 最快的方法是在页面中添加这个 <script> 标签,引入解析 jsx 语法的 babel 类库,注意后续的 script 标签块中使用了 jsx 语法,则一定要申明类型 type="text/babel" ,否则babel 将不进行解析 jsx 语法。<script type="text/babel">
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
重构 helloworld
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jsx重构helloworld</title> </head> <body> <div id="app"></div> <script src="./js/babel.min.js"></script> <script src="./js/react.development.js"></script> <script src="./js/react-dom.development.js"></script> <script type="text/babel"> ReactDOM.render( <div>你好世界</div>, document.getElementById('app'); ); </script> </body> </html>
<!-- 真实的 html 挂载点 --> <div id="root"></div> <!-- script 中的 type 属性一定要添加 , 否则默认就是 js 类型 --> <script type="text/babel"> // 使用 jsx 来完成 html 结构 // let vnode = <div>您好 React , 我是 jsx 语法</div> // 如果有换行 , 建议使用小括号 () , 括起来 let vnode = ( <div> <ul> <li>123</li> <li>456</li> </ul> </div> ) // 把虚拟 DOM 挂载到真实的 DOM 节点中 ReactDOM.render(vnode, document.querySelector('#root')) </script>
2.3、在 jsx 中语法中的 js 表达式
2.3.1、嵌入 JSX 表达式
在 jsx 语法中,要把 JS 代码写到单花括号 { } 中,所有标签必须要 闭合 。
let num = 100
let bool = false;
// JSX 语法
var myh1 = (
<div>
{/* 我是注释 */}
{num}
<hr />
{/* 三目运算 */}
{true ? "条件为真" : "条件为假"}
</div>
2.3.2、属性绑定动态值
const title = '你好世界';
// 一定要会使用它,这样用法在工作中天天用
<button title={title}>按钮</button>
<style>
/* class 是 es6 定义类的关键词,在 jsx 中不能使用,
只能通过 className 来调用定义好的样式类 */
.btn{color:red;}
</style>
// class => className 一定要牢记,因为在工作,写样式就要用到
// for => htmlFor
<button className="btn">按钮</button>
# jsx 中绑定样式 style 只绑定对象
<div style={ {color: 'red'} }></div>
# 动态显示 html 元素 dangerouslySetInnerHTML 可以进行对 html 标签进行反转义
# 在 react17 中 jsx 可以直接解析 html,但是对于转义后的 html 还不会自动转义,需要使用它
const html = 你好 ©世界
# 不转义 html 元素输出 { 两个下划线 _ _ html:html}
<div dangerouslySetInnerHTML={ {__html:html} }></div>
2.3.3、jsx 渲染数组列表
<script type="text/babel">
let arr = ["张三","李四","王五","赵六"];
let app = document.getElementById('app');
ReactDOM.render(
<div>
{/* jsx中如果是一维数组,直接写上就可以遍历渲染了 */}
{ arr }
</div>,
app
);
</script>
2.3.4、jsx 渲染数组列表并处理
<script type="text/babel">
let nameList = ['张三', '李四', '王五'];
ReactDOM.render(
<div>
{
// 方案1
nameList.map((item,index) => {
return (<h3>{item}</h3>)
});
// 方案2 【推荐】
nameList.map((item,index) => <h3>{item}</h3>);
</div>,
document.getElementById('app')
);
</script>
三、React 脚手架
React 团队主要推荐使用 create-react-app 来创建 React 新的单页应用项目的最佳方式。
React 脚手架 ( create-react-app ) 意义
- 脚手架是官方推荐,零配置,无需手动配置繁琐的工具即可使用
- 充分利用 Webpack,Babel,ESLint 等工具辅助项目开发
- 关注业务,而不是工具配置
create-react-app 会配置你的 开发环境 ,以便使你能够使用最新的 JavaScript 特性,提供良好的开发体验,并为生产环境优化你的应用程序。你需要在你的机器上安装 Node >= 8.10 和 npm >= 5.6 。
建议可以安装 js 包管理工具 yarn ( facebook 开发的 ) --- 速度会快一些
npm i -g yarn
3.1、创建 React 项目
npx create-react-app myapp // 创建项目,时间会有点的久
cd my-app // 进入到安装项目中
npm start // 启动 项目
若安装失败则换用指令 : npx create-react-app myapp --use-npm
安装失败导致的重新下载之前先将原来的半成品文件夹删除掉
=> 但是可能遇到以下删除不了文件夹的问题 :
( 你需要来自Administrators的权限才能对此文件夹进行更改 )
更改 package.json 文件内的配置项 : ( 防止自启动 )
"start": "set BROWSER=NONE && react-scripts start",
四、React 组件
4.1、简介
组件允许你将 UI 拆分为独立可复用的代码片段,并对每个片段进行独立构思。从概念上类似于 JavaScript 类 或 函数。它接受任意的 入参( props ),并返回用于描述页面展示内容的 React 元素( jsx )。 定义好的组件一定要有 返回值
react 中 定义组件 的方式2种
- 函数组件 ( 无状态组件 / UI组件 )
- 类组件 ( 状态组件 / 容器组件 )
4.2、组件的创建方式
4.2.1、函数创建组件
- 函数组件( 无状态组件 ):使用 JS 的 函数创建组件
- 函数名称必须以 大写字母开头,
- 函数组件必须有 返回值 ( jsx ),表示该组件的结构,且内容必须有 顶级元素
// 如果你在 VSCode 中安装了 jsx 插件,则可以用 rfc 创建 函数组件
4.2.2、类组件
- 使用 ES6 语法的 class 创建的组件( 状态组件 )
- 类名称必须要 大写字母开头
- 类组件要 继承 React.Component 父类,从而可以使用父类中提供的 方法 或者 属性
- 类组件必须提供 render 方法 ,用于页面结构渲染,结构必须要有顶级元素,且必须 return 去返回
// 注:如果你在 VSCode 中安装了 jsx 插件,可以使用 rcc 来创建类组件
4.3、父子组件传值(props[只读属性])
组件间传值,在 React 中是 通过 只读 属性 props 来完成数据传递的。
props:接受 任意 的入参,并返回用于描述页面展示内容的 React 元素。
props 中的数据是不能被修改的,只能读取。
props 是一个单向数据流。
4.3.1、函数组件
4.3.2、类组件
五、React 事件处理
5.1、事件绑定
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
- React 事件的命名采用 小驼峰式 ,而不是 纯小写 。
onClick onChange
- 使用 JSX 语法时你需要传入一个 函数 作为 事件处理函数,而不是一个字符串。
onClick = { this.fn }
// 绑定实现方法一定要用 { 函数 或 方法 } // 注 函数 或 方法 不能用小括号
- 类组件 与 函数组件 绑定事件是差不多的,只是在 类组件 中绑定事件函数的时候需要用到this,代表指向当前的类的引用,在函数中不需要调用 this ( 函数组件没有this )
- 函数组件
- 类组件
5.2、事件对象
React 中可以通过 事件处理函数 的 参数 获取到 事件对象 ,它的 事件对象 叫做:合成事件 ,即兼容所有浏览器,无需担心跨浏览器兼容问题,此事件对象还拥有和浏览器原生事件相同的接口,包括 stopPropagation() 和 preventDefault() ,如果你想获取到原生事件对象,可以通过 e.nativeEvent 属性来进行获取。
作用:获取 dom 元素 或 数据传值
react 中的实现没有提供像 Vue 中的 事件修饰符,像 冒泡 和 默认行为,需要开发者自行解决。
5.3、this 指向问题
在 JSX 事件函数方法中的 this ,默认不会绑定 this 指向。如果你忘记绑定,当你调用这方法的时候, this 的值为 undefined 。所以使用时一定要 绑定好 this 的指向。this 指向针对的是 类组件,函数组件没有 this 问题,因为 函数没有 this
- 构造方法中绑定 ( 只执行一次 , 所以性能最好 )
- 申明是使用 bind 绑定 ( 不能立刻执行 , 需要等待调用 )
- ( 不停的渲染 , 不停的绑定 , 性能稍差 )
<button onClick={this.fun.bind(this)}> 按钮 </button>
- 箭头函数 绑定
<button onClick={(evt) => this.fun(evt)}> 按钮 </button>
- 定义事件方法使用 箭头函数 来绑定
六、State 状态
state 状态只在 class 类组件才有,函数组件 没有此功能。
6.1、基本使用
- 状态 (state) 即 数据,是组件内部的 私有数据,只能在 组件 内部使用
- state 的值是对象,表示一个组件中可以有多个数据
- 通过 this.state 来 获取状态,react 中没有做 数据代理
- state 数据值可以 修改 , 使用 this.setState
- state 可以定义在类的 构造方法中 也可以写在类的 成员属性中
6.2、修改状态
state 中的值不能直接通过修改 state 中的值来进行修改数据操作,react 提供一个 this.setState 方法来完成 state 数据的 修改 操作
setState() 作用:
1.修改 state
2.更新 UI
注:setState 本身并不是异步,只是因为 react 的性能优化机制体现为异步。
在 react 的生命周期函数 或者 作用域下为 异步,在原生的环境下为 同步。
总结:setState 即是 异步也是同步
语法1
this.setState({
key:value
})
语法2 推荐
this.setState(state => {
return {key:value}
})
## 异步
state = {
number:1
};
componentDidMount(){
this.setState({number:3},()=>{
// 获取最新的修改数据
console.log(this.state.number)
})
}
## 同步
// 在延时器中
state = {
number:1
};
componentDidMount(){
setTimeout(()=>{
this.setState({number:3})
console.log(this.state.number)
},0)
}
// 在原生事件中
state = {
number:1
};
componentDidMount() {
document.body.addEventListener('click', this.changeVal, false);
}
changeVal = () => {
this.setState({
number: 3
})
console.log(this.state.number)
}
- setState 聚合用法 :
6.3、props 与 state 区别
- props 中存储的数据,都是 外界传递 到组件中的
- props 中的数据,都是 只读 的
- state 中的数据,都是 可读可写 的
- props 在 函数声明 或 类申明 的 组件 中都有
- state 只有 类 申明的组件中才有
七、props 进阶
7.1、children 属性
children 属性,表示 组件标签的 子节点,当组件标签有子节点时,props 就会有该属性,与普通的props 一样,其值可以是 任意类型。单标签 和 双标签 中没有数据都是没有此属性。
实现类似于 作用域插槽 功能 :
虚拟 DOM 我们没有办法直接修改 ,
类型为 唯一值 , Symbol ( 私有的 ), 不能对其修改 ,
所以我们可以克隆过来一个( 自己的了 )进行修改
7.2、类型限制(prop-types)
对于组件来说,props 是外部传入的,无法保证组件使用者传入什么格式的数据,简单来说就是组件调用者可能不知道组件封装着需要什么样的数据,如果传入的数据不对,可能会导致程序异常,所以必须要对于 props 传入的 数据类型 进行 校验。
- 安装校验包
npm i -S prop-types
"prop-types": "^15.7.2"
import React, { Component } from 'react';
import Child from './components/Login';
class App extends Component {
fn = () => console.log('fn')
render() {
return (
<div>
{/* <Child age={100} /> */}
{/* <Child age="100" /> */}
{/* <Child arg="111" sex="男" age={100} arr={[1, 2, 3]} fn={this.fn} obj={{ id: 1, name: 'aa' }} /> */}
<Child age="100" />
</div>
);
}
}
export default App;
console.log(typeof this.props.age);
console.log(Array.isArray(this.props.age));
console.log(typeof this.props.age === 'object' && this.props.age instanceof Array);
console.log('push' in this.props.age); // 原型链
console.log(Object.prototype.toString.call(this.props.age) === '[object Array]');
console.log(({}).toString.call(this.props.age) === '[object Array]');
7.3、默认值(defaultProps)
如果 props 没有属性没有传过数据,为了不让程序异常,可以设置其 默认值。
八、表单处理
8.1、受控组件
将 state 与 表单项中的 value 值绑定在一起,由 state 的值来控制表单元素的值,称为 受控组件。
绑定步骤:
- 在 state 中添加一个状态,作为表单元素的 value 值
- 给表单元素绑定 change 事件,将表单元素的值设置为 state 的值
8.2、非受控组件
没有和 state 数据源进行关联的 表单项,而是 借助 ref ,使用元素 DOM 方式获取表单元素值
使用步骤 :
- 调用 React.createRef( ) 方法创建 ref 对象
- 将创建好的 ref 对象添加到文本框中
- 通过 ref 对象获取到文本框的值
内存泄漏 ,
简写 ref :
图例 :
跳转链接 => React_02 学习笔记
跳转链接 => React_03 学习笔记
跳转链接 => React_04 菜谱项目
跳转链接 => React_05 Hooks