React 详解
- 1、React简介
- 1.1、React的特点
- 1.2、React高效的原因
- 1.3、JSX
- 1.3.1、JSX说明
- 1.3.2、渲染虚拟DOM(元素)
- 2、三大核心属性
- 2.1、state状态
- 2.2、props数据
- 2.3、ref节点
- 3、React生命周期
- 4、React-Cli
- 5、React-Router5
- 5.1、BrowserRouter
- 5.2、Link
- 5.3、NavLink
- 5.4、Navigate
- 5.5、Router和Routers
- 5.6、Redirect
1、React简介
React官网 https://react.docschina.org/
本人git demo地址:https://gitee.com/lizuoqun/web-react-lzq
1.1、React的特点
- 声明式编码
- 组件化编码
- React Native 编写原生应用
- 高效(优秀的Diffing算法)
1.2、React高效的原因
- 使用虚拟(virtual)DOM, 不总是直接操作页面真实DOM。
- DOM Diffing算法, 最小化页面重绘。
1.3、JSX
1.3.1、JSX说明
- 全称: JavaScript XML
- react定义的一种类似于XML的JS扩展语法: JS + XML本质是
React.createElement(component, props, ...children)
方法的语法糖 - 作用: 用来简化创建虚拟DOM
- 写法:
var ele = <h1>Hello JSX!</h1>
- 注意1:它不是字符串, 也不是HTML/XML标签
- 注意2:它最终产生的就是一个JS对象
- 标签名任意: HTML标签或其它标签
- 标签属性任意: HTML标签属性或其它
- 基本语法规则
- 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
- 遇到以 { 开头的代码,以JS语法解析: 标签中的js表达式必须用{ }包含
1.3.2、渲染虚拟DOM(元素)
- 语法: ReactDOM.render(virtualDOM,DOM)
- 作用: 将虚拟DOM元素渲染到页面中的真实容器DOM中显示
- 参数说明
- 参数一: 纯js或jsx创建的虚拟dom对象
- 参数二: 用来包含虚拟DOM元素的真实dom元素对象(一般是一个div)
2、三大核心属性
2.1、state状态
- state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
- 组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
使用状态数据需要注意:
- 组件中render方法中的this为组件实例对象
- 组件自定义的方法中this为undefined,如何解决?
- 强制绑定this: 通过函数对象的bind()
- 箭头函数
- 状态数据,不能直接修改或更新
案例:定义一个展示天气信息的组件:默认展示天气炎热 或 凉爽,点击文字切换天气
<script type="text/babel">
class Num extends React.Component {
// 借助构造器初始化状态
constructor(props) {
super(props);
this.state = { isOne: true };
// 绑定this
this.changeState = this.changeState.bind(this);
}
changeState() {
// 这里的this对象是undefined?
// console.log(this)
console.log("change");
// 状态不能直接更改
// this.state.isOne = !this.state.isOne;
// 通过setState方法进行修改值,并且通过这种方法进行设置值,只会覆盖原状态下的键值,其余键值不变
this.setState({ isOne: !this.state.isOne });
console.log(this);
}
render() {
// console.log(this);
// 读取状态进行渲染判断
return (
// 绑定事件、初始化渲染时不调用函数
<h2 onClick={this.changeState}>
this is {this.state.isOne ? "one" : "zero"}
</h2>
);
}
}
ReactDOM.render(<Num />, document.getElementById("app1"));
</script>
对于这样编写代码来进行实现,还可以对代码进行简化一些:
<script type="text/babel">
class Num extends React.Component {
state = { isOne: true };
// 自定义方法,指向一个箭头函数,箭头函数内部的this等价于外部第一个的this,也就等于该类的this,故可以直接通过this拿到state
changeState = () => {
this.setState({ isOne: !this.state.isOne });
};
render() {
return (
<h2 onClick={this.changeState}>
this is {this.state.isOne ? "one" : "zero"}
</h2>
);
}
}
ReactDOM.render(<Num />, document.getElementById("app1"));
</script>
2.2、props数据
- 每个组件对象都会有props(properties的简写)属性
- 组件标签的所有属性都保存在props中
props的作用:
- 通过标签属性从组件外向组件内传递变化的数据
- 注意: 组件内部不要修改props数据
案例:自定义用来显示一个人员信息的组件
- 姓名必须指定,且为字符串类型;
- 性别为字符串类型,如果性别没有指定,默认为男
- 年龄为字符串类型,且为数字类型,默认值为18
<script type="text/babel">
class Person extends React.Component {
render() {
console.log(this);
// props 不可修改
const { name, age, sex, date } = this.props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age + 1}</li>
<li>性别:{sex}</li>
<li>日期:{date}</li>
</ul>
);
}
}
// 设置校验规则
Person.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
spack: PropTypes.func,
};
// 设置默认值
Person.defaultProps = {
sex: "未知",
date: Date(),
};
function spack() {
console.log("spack...");
}
ReactDOM.render(
<Person name="hyy" age="18" sex="男" spack={spack} />,
document.getElementById("app")
);
const p = { name: "张三", age: 18 };
ReactDOM.render(<Person {...p} />, document.getElementById("app1"));
ReactDOM.render(
<Person name="18" age={18} />,
document.getElementById("app2")
);
</script>
还可以通过函数来进行定义组件使用props
<script type="text/babel">
function Demo(props) {
const { name, age, sex, date } = props;
return (
<ul>
<li>姓名:{name}</li>
<li>年龄:{age}</li>
<li>性别:{sex}</li>
<li>日期:{date}</li>
</ul>
);
}
// 设置校验规则
Demo.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
spack: PropTypes.func,
};
// 设置默认值
Demo.defaultProps = {
sex: "未知",
date: Date(),
};
const p = { name: "张三", age: 18 };
ReactDOM.render(<Demo {...p} />, document.getElementById("app1"));
</script>
2.3、ref节点
组件内的标签可以定义ref属性来标识自己,本质上和给标签定义id是一样的。
基本使用:
<script type="text/babel">
class Demo extends React.Component {
showData = () => {
// const leftInput = document.getElementById("input1").value;
// alert(leftInput);
alert(this.refs.ref1.value);
};
blurData = () => {
alert(this.refs.ref2.value);
};
render() {
return (
<div>
<input
ref="ref1"
id="input1"
type="text"
placeholder="点击按钮提示"
/>
<button onClick={this.showData}>提示</button>
<input
ref="ref2"
onBlur={this.blurData}
type="text"
placeholder="失去焦点提示"
/>
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("app"));
</script>
使用回调的ref
<script type="text/babel">
class Demo extends React.Component {
showData = () => {
alert(this.input1.value);
};
blurData = () => {
alert(this.input2.value);
};
render() {
return (
<div>
<input
ref={(currentNode) => {
this.input1 = currentNode;
}}
id="input1"
type="text"
placeholder="点击按钮提示"
/>
<button onClick={this.showData}>提示</button>
<input
ref={(currentNode) => {
this.input2 = currentNode;
}}
onBlur={this.blurData}
type="text"
placeholder="失去焦点提示"
/>
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("app"));
</script>
使用createRef API创建
<script type="text/babel">
class Demo extends React.Component {
myRef = React.createRef();
showData = () => {
console.log(this.myRef);
alert(this.myRef.current.value)
};
render() {
return (
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示" />
<button onClick={this.showData}>提示</button>
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("app"));
</script>
3、React生命周期
组件的生命周期可分成三个状态:
Mounting(挂载):已插入真实 DOM
Updating(更新):正在被重新渲染
Unmounting(卸载):已移出真实 DOM
在React16版本之前的生命周期:
- 初始化阶段: 由ReactDOM.render()触发—初次渲染
- constructor()
- componentWillMount()
- render()
- componentDidMount()
- 更新阶段: 由组件内部this.setSate()或父组件重新render触发
- shouldComponentUpdate()
- componentWillUpdate()
- render()
- componentDidUpdate()
- 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount()
在React16版本之后的生命周期:
- 初始化阶段: 由ReactDOM.render()触发—初次渲染
- constructor()
- getDerivedStateFromProps
- render()
- componentDidMount()
- 更新阶段: 由组件内部this.setSate()或父组件重新render触发
- getDerivedStateFromProps
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate
- componentDidUpdate()
- 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount()
4、React-Cli
安装依赖与创建项目
全局安装
npm i -g create-react-app
创建项目
create-react-app web-lzq-react
如果安装create-react-app还是无法创建项目可使用以下命令进行操作
npx create-react-app web-lzq-react
启动项目
npm start
项目文件目录说明
文件目录名 | 说明 | |
public | 静态资源文件夹 | |
favicon.icon | 网站页签图标 | |
index.html | 主页面 | |
logo192.png | logo图 | |
logo512.png | logo图 | |
manifest.json | 应用加壳的配置文件 | |
robots.txt | 爬虫协议文件 | |
src | 源码文件夹 | |
App.css | App组件的样式 | |
App.js | App组件 | |
App.test.js | 用于给App做测试 | |
index.css | 样式 | |
index.js | 入口文件 | |
logo.svg | logo图 | |
reportWebVitals.js | 页面性能分析文件(需要web-vitals库的支持) | |
setupTests.js | 组件单元测试的文件(需要jest-dom库的支持) |
5、React-Router5
如果你了解vue-router,那么对于react-router来说就相对来说比较容易理解,React Router 是一个用于 React 的全功能客户端和服务器端路由库,它是一个用于构建用户界面的 JavaScript 库。React Router 可以在任何 React 运行的地方运行;在 web 上,在带有 node.js 的服务器上,以及在 React Native 上。
安装react-router5
npm install react-router-dom@5
5.1、BrowserRouter
BrowserRouter是在 Web 浏览器中运行 React Router 的推荐界面。A使用干净的 URL 将当前位置存储在浏览器的地址栏中,并使用浏览器的内置历史堆栈进行导航。
ReactDOM.render(
<BrowserRouter>
</BrowserRouter>,
root
);
5.2、Link
它允许用户通过单击或点击来导航到另一个页面。在react-router-dom中,Link呈现一个可访问的<a>
元素,其href指向它链接到的资源。
<Link to='/home'>Home</Link>
5.3、NavLink
默认情况下,当组件处于活动状态时,active类会被添加到<NavLink>
组件中。这为从 v5 升级的大多数用户提供了相同的简单样式机制。简单来说,NavLink和Link的区别就是是否可以用来控制当前选择的路由的样式
<NavLink className="list-group-item " to="/home/news">
News
</NavLink>
5.4、Navigate
navigate顾名思义是导航的意思,当元素呈现时就会更改当前位置。
<Navigate to="/home" />
5.5、Router和Routers
这两个表达的意思就相当于一串的路由数据,当进行页面路由访问的时候还会从上至下进行逐层判断是否跳转
<Routes>
<Route path="/lzq/about" component={About}></Route>
<Route path="/lzq/home" component={Home}></Route>
<Route path="/about" component={About}></Route>
</Routes>
5.6、Redirect
Redirect 重定向
<Redirect to="/null"></Redirect>