文章目录
React 是什么?
React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库,主要用于构建UI界面
通过script引入使用,仅用于学习调试使用
方式一:
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
方式二:
安装:
npm i react
npm i react react-dom
引入:<script src="../node_modules/react/umd/react.development.js"></script>
<script src="../node_modules/react-dom/umd/react-dom.development.js"></script>
版本:
cjs:commonJS
esm:ESModule
umd:通用模块
react开发环境的搭建
- react.js 核心文件
- react-dom.js 渲染页面中的DOM,当前文件依赖于核心文件
- babel.js ES6转换成ES5 、JSX语法转换成javascript 现今浏览器进行代码的兼容
安装
初始化项目: npm init -y
npm i react -S
npm i react-dom -S
npm i babel-standalone -S
react特点
-
虚拟 DOM;
-
组件化;
-
声明式代码;
-
单向数据流;
-
轻量级的js库;
创建虚拟节点:React.createElement(type,props,children)
渲染虚拟节点:React.render(vNode,target)
react-dom
挂载节点,将jsx写的虚拟dom变成真的dom
render
每次都是新旧虚拟dom之间进行比较,之后才会生成真实dom
react原理
虚拟dom
diff算法
JSX
(javascript xml) javascript的扩展性语法
优点
- 执行的效率高
- 他是类型安装,编译的过程中就能及时发现错误
- 使用JSX编写模板更加简单快速
语法
- 组件首字母大写
- return 内容需要一个大的容器包裹,如果我们无需增加一个大的容器,可以用
Fragment
进行包裹,编译后就没有更多的htmlDom树了 - 注释写法
{/* 下面inout框 */}
- html 里写样式类名,需要写成
className="input"
才能识别 - 如果输出的富文本能够识别html标签只要
dangerouslySetInnerHTML = {{__html:item}}
- 聚集光标原本for是跟循环冲突,需要写成
htmlFor
- JSX编译 JSX —>createElement ----> 虚拟DOM(JS对象 )—> 真实的 DOM
- 如果使用了JSX语法需要引入
import React from 'react';
组件
- 函数组件(无状态组件,UI组件)(优先使用)
- 类组件(状态组件: state、this、生命周期函数)
组件数据渲染方式
- props
- 函数组件的第一个参数就是props
- 类组件:
- constructor的第一个参数
- this.props
- state:只能在类组件中使用
- 获取:this.state.xxx
- 设置:this.setState(newState,callback)
- newState:Object | Function
组件通讯
父 -> 子:props
子 -> 父:利用props把父组件的方法传到子组件执行,并传递数据
深层次传递
-
context组件共享、
所谓context,就是联系上下文
- 创建Context
- 父组件Provider
- 子组件接收
注意!!!
现在高版本的React都是将propTypes单独继承为一个js文件用于外部引入,而不是老版本的React.Proptypes.string.xxxxx。
<!-- 引入propTypes,用于对组件标签属性进行限制 -->
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/babel">
// 创建组件
class Person extends React.Component{
constructor(props){
// 构造器是否接收props,是否传递给super,取决于:是否希望在构造器中通过this访问props
// 所以,类中的构造器能省略就省略,开发的时候基本不写构造器
console.log(props);
super(props);
}
render(){
const {name,sex,age} = this.props;
// this.props.name = "Jack"; //此行代码会报错,因为props是只读的,不可修改
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
注意!!!
一定要注意大小写
将标签属性的限制和默认值设定写在类组件里面,利用static静态修饰,相当于为类自身加属性,而不给类的实例对象加该属性。
// 对标签属性进行类型、必要性的限制
static propTypes = {
name:PropTypes.string.isRequired, /* 字符串类型,必传 */
sex:PropTypes.string,
age:PropTypes.number,
// speak:PropTypes.func, //限制speak必须为一个函数传递过来
}
// 指定默认标签属性值
static defaultProps = {
sex:"保密",
age:18,
}
}
ReactDOM.render(<Person name="Tom"/>,document.getElementById('test1'))
</script>
context
context指的是函数的执行上下文,函数被调用时,this指向谁,谁就是当前的执行上下文;
context api给出三个概念:React.createContext()、Provider、Consumer;
-
React.createContext()
这个方法用来创建context对象,并包含Provider、Consumer两个组件 <Provider />、<Consumer /> const {Provider, Consumer} = React.createContext();
-
Provider
数据的生产者,通过
value
属性接收存储的公共状态,来传递给子组件或后代组件 -
Consumer
数据的消费者,通过订阅Provider传入的context的值,来实时更新当前组件的状态
注意:每当Provider的值发生改变时, 作为Provider后代的所有Consumers都会重新渲染
props单向数据流动:(Props传递数据很繁琐)
context跨组件传递数据:
组件刷新的场景
所谓的刷新组件,就是执行组件的render函数
-
state改变:nextState(将要改变的值) 与this.state(当前值)
-
props改变:nextProps(将要改变的值) 与this.props当前值)
-
父组件刷新
子组件也会跟着刷新(但这种刷新没必要,可以利用shouldComponentUpdate优化
更简单的优化方式:PureComponent)
props属性
1.父组件调用子组件时传入属性
2.子组件直接通过this.props.属性名 即可拿到父组件传过来的值
4.在父组件里定义一个函数
5.调用子组件时将函数传过去
6.子组件通过this.props.函数名()来调用函数并且执行
import React, { Component,Fragment} from 'react';
//React的props传参
// 父组件
class App extends Component {
render() {
return (
<Fragment>
<Child aaa="红牛" bbb={this.hanshu}></Child>
</Fragment>
)
}
hanshu(){
return "我是父组件传过来的函数"
}}
// 子组件
class Child extends Component{
render(){
return (
<div>{this.props.aaa}{this.props.bbb()}</div>
)
}
}
export default App;
生命周期函数
只有在类组件中才存在生命周期函数,生命周期函数中的this指向组件实例
定义组件
-
定义类组件
继承React.Component-会有生命周期和
this
- ES6 class
- React.createClass() //老式方法
-
Initial:初始化阶段
- constructor():初始化state、改变函数this的指向
-
Mounting:挂载阶段
- componentWillMount(弃用)
- componentDidMount:发送ajax请求、位置定时器、DOM节点操作、读取本地存储数据
-
Updating:更新阶段
执行setState()会进入更新阶段
-
componentWillUpdate(弃用)
-
componentDidUpdate
在该生命周期函数中修改state时,要注意避免死循环
-
-
Unmounting:卸载阶段
- componentWillUnmount
-
特殊生命周期函数
-
componentWillReceiveProps
-
shouldComponentUpdate(nextProps, nextState)
该生命周期函数一定要返回Boolean(true:允许渲染 false:不允许渲染),一般用于优化组件性能
-
搭建 webpack的react环境
创建目录:dist、public、src(main.js)、webpack.config.js、package.json
初始化项目
npm init -y
安装及配置依赖
npm i react react-dom
npm i webpack webpack-cli webpack-dev-server
npm i @babel/core babel-loader @babel/preset-react
npm i html-webpack-plugin
webpack配置
module.exports = {
//入口
entry:path.join(_dirname,'src/main.js'),
//出口
//output:{
path:path.join(_dirname,'dist'),
filename:"[name]-[hash:5]-bundle.js" //打包后输出的文件名
},
devServer:{
// 服务器根目录
contentBase:path.join(_dirname,'./public')
},
//加载器loader:用于编译代码(每一种文件类型都需要相应loader)
module:{
rules:[
{
test:/\.js$/i,
use:[{
//babel-loader处理js代码
loader:'babel-loader',
options:{
//plugins:[],//babel插件
presets:['@babel/preset-react'],//bable插件集
}
}]
},
//css加载器:css-loader,style-loader
{
text:/\.css$/,
use:['style-loader','css-loder'] //从右往左 先css后style
},
//sass加载器:sass-loader,node-sass
{
text:/\.scss$/,
use:['style-loader','css-loder','sass-loader']
},
]
},
//插件
plugins:{
//用来创建html页面
new HtmlwebpackPlugin({
template:'./public/template.html',
//filename:'login.html', //默认index.html
})
}
}
不断学习,不断更新…