网址:https://zh-hans.reactjs.org/
React 起源于 Facebook(脸书) 的内部项目,它是一个用于构建用户界面的 javascript 库,Facebook用它来架设公司的Instagram网站,并于2013年5月开源。
因为是库,只做界面展示,所以可以二次开发,阿里就是Rax。
- 声明式
你只需要描述UI看起来是什么样式,就跟写HTML一样,React负责渲染UI,数据的声明
- 基于组件
组件时React最重要的内容,组件表示页面中的部分内容 -- react元素 -- 虚拟dom
- 学习一次,随处使用
使用React可以开发Web应用(React-dom),使用React可以开发移动端(react-native),可以开发VR应用(react 360)
Vue是一个框架。
React可以说它不是框架,它只是一个构建页面的JavaScript库,但是外面也认为其是一个框架。
Chrome 浏览器扩展:https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=zh-CN
国内:极简插件_Chrome扩展插件商店_优质crx应用
vscode安装react开发扩展
需要注意,在react中,JavaScript代码部分里面如果涉及到DOM的class属性操作,请不要直接使用class
,原因是这个class
是es6里面的关键词,react里面需要使用className
进行替换
引入到当前的网页中
1. // React 的核心库 实现跨平台开发(pc、移动)就是创建虚拟Dom的核心库
2. //DOM 相关的功能 就是实现把虚拟DOM转为真实dom
虚拟dom的key是起到标识的作用,方便比对。
参数1:组件名 或 html标签。参数2:object | null 属性(style必须是{})。参数3:子节点(可以多个)。
通过ReactDOM.render()方法把虚拟Dom转为真实Dom。
由于通过React.createElement()方法创建的React元素有一些问题,代码比较繁琐,结构不直观,无法一眼看出描述的结构,不优雅,开发时写代码很不友好。
React使用 JSX 来替代常规的JavaScript,JSX 可以理解为的JavaScript语法扩展,它里面的标签申明要符合XML规范要求。
jsx浏览器认识吗?
答:浏览器只能识别 js,对于jsx不能识别。浏览如果来识别jsx呢?
答:react工程化中内置了一个将jsx=》js的编译工具 => babel
xml是什么?
答:严格的标记性语言。
简单的理解,xml当作是一个严格的html语言
标签有开始就必须要有结束
属性值必须要有引号括起来,属性名不要大写
/>
React不一定非要使用JSX,但它有以下优点:
- JSX 执行更快,因为它在编译为JavaScript代码后进行了优化
jsx是浏览不能够直接运行的,它需要一个转译器进行转译(babel),转为js
- 它是类型安全的,在编译过程中就能发现错误
- 声明式语法更加直观,与HTML结构相同,降低了学习成本,提升开发效率速
jsx语法中一定要有一个顶级元素包裹,否则编译报错,程序不能运行
js != jsx jsx => js+xml集合版本,js增强版,js有的它有,js没有它也有
一定要申明类型 type="text/babel"
默认是 type="text/JavaScript"
在项目中尝试 JSX 最快的方法是在页面中添加这个
let num = 100
let bool = false;
// JSX 语法
var myh1 = (
{/* 我是注释 */}
{num}
{true ? "条件为真" : "条件为假"}
)
const title = '你好世界';
// class --> className一定要牢记,因为在工作,写样式就要用到
// for --> htmlFor
# 在react17中jsx可以直接解析html,但是对于转义后的html还不会自动转义,需要使用它
# 不转义html元素输出 {两个下划线html:html}
React团队主要推荐使用create-react-app来创建React新的单页应用项目的最佳方式。
第三方的,官方觉得不错,就用了。
React脚手架(create-react-app)意义
create-react-app会配置你的开发环境,以便使你能够使用最新的 JavaScript特性,提供良好的开发体验,并为生产环境优化你的应用程序。
你需要在你的机器上安装 Node >= 8.10 和 npm >= 5.6。
建议可以安装 js包管理工具 yarn (facebook开发的) --- 速度会快一些
npm i -g yarn
npx create-react-app 项目名 // 创建项目,时间会有点的久
纯字母,不能大写,不能带空格
cd 项目名 // 进入到安装项目中
npm start // 启动项目
npx 就是5.6之后自带的,属于在线使用create-react-app
npm i -D cross
yarn add cross-env --dev
官网
调试 npm start 的命令
或
组件允许你将 UI 拆分为独立可复用的代码片段,并对每个片段进行独立构思。从概念上类似于 JavaScript 类或函数。
函数组件 (无状态组件/UI组件)
类组件 (状态组件/容器组件)
一个个jsx就是一个个组件。
- 函数组件(无状态组件):使用JS的函数创建组件
- 函数名称必须以大写字母开头,
- 函数组件必须有返回值(jsx),表示该组件的结构,且内容必须有顶级元素
import React from 'react'
// 函数名首字母必须大写
function Hello() {
return (
这是第一个函数组件
)
}
export default Hello;
- 使用ES6语法的class创建的组件(状态组件)
- 类名称必须要大写字母开头
- 类组件要继承React.Component父类,从而可以使用父类中提供的方法或者属性
- 类组件必须提供 render 方法,用于页面结构渲染,结构必须要有顶级元素,且必须return去返回
import React from 'react'
// 创建class类,继承React.Component,在里面提供render方法,在return里面返回内容
class Hello extends React.Component{
render(){
return (
这是第一个类组件
)
}
}
props中的数据是不能被修改的,只能读取。
组件间传值,在React中是通过只读属性 props 来完成数据传递的。
props:接受任意的入参,
并返回用于描述页面展示内容的 React元素。
props是一个单向数据流。
【父】通过属性方式传参
【子】通过函数入参props接收,然后解构{}使用
【父】通过属性方式传参
【子】通过props接收,然后解构{}使用
父
子
React 元素的事件处理和 DOM 元素的很相似,但是有一点语法上的不同:
React 事件的命名采用小驼峰式,而不是纯小写。onClick onChange
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
onClick={ this.fn} // 绑定实现方法一定要用{函数或方法}
// 注函数或方法默认不用小括号,否则加 箭头
- 类组件与函数组件绑定事件是差不多的,只是在类组件中绑定事件函数的时候需要用到this,代表指向当前的类的引用,在函数中不需要调用this
函数组件
类组件
类组件的强制刷新视图
改变this跑偏的问题:也是用箭头函数柯里化。
React中可以通过事件处理函数的参数获取到事件对象,
即兼容所有浏览器,无需担心跨浏览器兼容问题,此事件对象还拥有和浏览器原生事件相同的接口,包括 stopPropagation()和 preventDefault(),
如果你想获取到原生事件对象,可以通过 e.nativeEvent 属性来进行获取。
react中的实现没有提供像vue中的事件修饰符,像冒泡和默认行为,需要开发者自行解决。
在JSX事件函数方法中的 this,默认不会绑定 this指向。如果你忘记绑定,当你调用这方法的时候, this 的值为 undefined。所以使用时一定要绑定好this的指向。
constructor(props){
super(props)
// 在构造方法中指定this指向
this.fun = this.fun.bind(this)
}
// 通过箭头函数定义事件方法,也能解决this指向问题
state状态只在class类组件才有,函数组件没有此功能。
函数组件在react16.8以后提供了hooks辅助函数来模拟状态。
状态(state)即数据,是组件内部的私有数据,只能在组件内部使用 (读取和修改)
state的值是对象,表示一个组件中可以有多个数据
通过this.state来获取状态,react中没有做数据代理
state数据值可以修改,但是想要让视图更新必须用 this.setState
state可以定义在类的构造方法中也可以写在类的成员属性中
state中的值不能直接通过修改state中的值来进行修改数据操作,react提供一个this.setState方法来完成state数据的修改操作
props.children属性,表示组件标签的子节点,当组件标签有子节点时,props就会有该属性,与与普通的props一样,其值可以使任意类型。单标签和双标签中没有数据都是没有此属性。
在父组件的【子组件双标签】内写东西,在子可以通过【this.props.chidren】使用。
对于组件来说,props是外部传入的,无法保证组件使用者传入什么格式的数据,简单来说就是组件调用者可能不知道组件封装着需要什么样的数据,如果传入的数据不对,可能会导致程序异常,所以必须要对于props传入的数据类型进行校验。
#安装校验包
npm i -S prop-types
# 在组件中导入
import PropTypes from 'prop-types'
# 约束类型
使用 PropTypes 进行类型检查 – React
//# 函数组件
function App(){}
// 验证规则
App.propTypes = {
prop-name:PropTypes.string
}
//# 类组件
class App extends Component{
// 类内部完成 检查
static propTypes = {
prop-name:PropTypes.string
}
}
如果props没有属性没有传过数据,为了不让程序异常,可以设置其默认值。
//# 函数组件
function App(){}
App.defaultProps = {
title: '标题'
}
//# 类组件
class App extends Component {
static defaultProps = {
title: '标题'
}
}
称为受控组件。
绑定步骤:
子传父
删除写在父
子接收返回index
单个复选框
多个复选框
全选
复选完成全选
没有和state数据源进行关联的表单项,而是借助ref,使用元素DOM方式获取表单元素值
使用步骤
函数组件无生命周期,生命周期只有才拥有。
生命周期函数指在某一时刻组件会自动调用并执行的函数。React每个类组件都包含生命周期方法,以便于在运行过程中特定的阶段执行这些方法。例如:我们希望在第一次将其呈现到DOM时设置一个计时器Clock。这在React中称为“安装”。我们也想在删除由产生的DOM时清除该计时器Clock。这在React中称为“卸载”。
React lifecycle methods diagram
挂载时执行,构造方法,第1个执行的方法,只执行一次,一般做初始化
React组件的构造函数在挂载之前被调用。在实现React.Component构造函数时,需要先在添加其它内容前,调用super(props),用来将父组件传来的props绑定到继承类中。
副作用钩子方法
在挂载和更新都会执行,n次
此方法是react16.3之后新增,会在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。
此方法适用于罕见的用例,即当前组件的 state 的值在任何时候都取决于 props传入。
更新了会触发他 ,一更新数据就变回刚接收的状态了,所以不要直接 return nextProps
render()方法是必需的,它主要负责组件的渲染,会被重复调用n次
能写网络请求,但是不能更新,会死循环
最消耗性能:
优化,把继承的Component 换成 PrueComponent,但是\
所以优化换成update
自己写太麻烦
yarn add lodash
祖先节点状态发生改变,自己会更新,对自己没影响时要不更新做优化.
它会在组件挂载后(插入 DOM 树中)立即调用。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。
减少组件的重复渲染
当 props 或 state 发生变化时,shouldComponentUpdate() 会在渲染执行之前被调用。返回值默认为 true则组件继续渲染,为false则当前组件不会渲染。首次渲染或使用 forceUpdate() 时不会调用该方法。此方法仅作为性能优化的方式而存在。你也可以考虑使用内置的 PureComponent 组件,而不是手动编写 shouldComponentUpdate()。PureComponent 会对 props 和 state 进行浅层比较,并减少了跳过必要更新的可能性。
当this.setState()修改了state中的数据后,当前组件将重新渲染,同时也会重新渲染子组件,但只会渲染当前组件子树(当前组件以其所有子组件)
在最近一次渲染输出(提交到 DOM 节点)之前调用。它使得组件能在发生更改之前从 DOM 中捕获一些信息,此生命周期的任何返回值将作为参数传递给 componentDidUpdate()
会在数据更新后会被立即调用。首次渲染不会执行此方法。
会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作
在react没有类似vue中的事件总线来解决这个问题。在实际的项目中,当需要组件间跨级访问信息时,如果还使用组件层层传递props,此时代码显得不那么优雅,甚至有些冗余。在react中,我们还可以使用context来实现跨级父子组件间的通信。
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据。
在React的Context中,数据我们可当成商品,发布数据的组件会用provider身份(卖方),接收数据的组件使用consumer身份(卖方)
子孙
改数据
npm i -S axios
在配置在src/setupProxy.js文件,并通过npm安装http-proxy-middleware,代理中间件模块
安装模块
npm i -S http-proxy-middleware
const {createProxyMiddleware: proxy} = require('http-proxy-middleware')
module.exports = app => {
app.use('/api', proxy({
target: 'http://localhost',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}))
}
高阶组件(Higher-Order Components)就是一个函数,传给它一个组件,它返回一个新的组件。
高阶组件:就相当于手机壳,通过包装组件,增强组件功能。
实现步骤:
进行权限控制
路由限制
访问统计
统一布局(公共样式,头尾)
返回类的话要这样
装饰器是一种函数,写成 @函数名。它可以放在类和类方法的定义前面。react脚手架创建的项目【默认是不支持装饰器】,需要手动安装相关模块和添加配置文件。
npm i -D customize-cra react-app-rewired
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
此文件就是react工程用于增量配置react中的webpack配置,
可以理解为就是webpack.config.js的扩展文件,是给node所用,commonjs规范。
const {resolve}= require('path')
const {addDecoratorsLegacy, override} = require('customize-cra')
const customize = () => (config) => {
config.resolve.alias['@'] = resolve('./src')
return config
}
module.exports = override(
addDecoratorsLegacy(),
customize()
)
jsconfig.json要配置,和vue一样
根据用户名,显示不同的电话号码权限
不是admin的显示123****4564
连续两次相同传参,第二次会直接返回上次的结果,每次传参不一样,就直接调用函数返回新的结果,会丢失之前的记录,并不是完全记忆,可以在它的参数中传入state数据从而实现了类似Vue中的计算属性功能
npm i -S memoize-one
yarn add memoize-one
# 引入
import memoizeOne from 'memoize-one'
# 使用
getValue = memoizeOne((x,y) => x+y)
用它是因为本身直接引css没有作用域
代码提示
CSS-in-JS是一种技术,而不是一个具体的库实现。简单来说CSS-in-JS就是将应用的CSS样式写在JavaScript文件里面,而不是独立为一些css,scss或less之类的文件,这样你就可以在CSS中使用一些属于JS的诸如模块声明,变量定义,函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义。CSS-in-JS在React社区的热度是最高的,这是因为React本身不会管用户怎么去为组件定义样式的问题,而Vue有属于框架自己的一套定义样式的方案。
styled-components 应该是CSS-in-JS最热门的一个库,通过styled-components,你可以使用ES6的标签模板字符串语法,为需要styled的Component定义一系列CSS属性,当该组件的JS代码被解析执行的时候,styled-components会动态生成一个CSS选择器,并把对应的CSS样式通过style标签的形式插入到head标签里面。动态生成的CSS选择器会有一小段哈希值来保证全局唯一性来避免样式发生冲突。
npm i -S styled-components
样式文件就是.js文件
现代的前端应用大多数是SPA(单页应用程序),也就是只有一个HTML页面的应用程序。因为它的用户体验更好、对服务器压力更小,所以更受欢迎。为了有效的使用单个页面来管理多页面的功能,前端路由应运而生。
通过组件完成路由规则的定义
可以通过代码做 [ 配置式路由 ]
Declarative routing for React apps at any scale | React Router
npm i -S react-router-dom@5
最新是6,所以要写@5
Router: HashRouter和BrowserRouter
HashRouter: 使用URL的哈希值实现 (localhost:3000/#/first)
BrowserRouter:使用H5的history API实现(localhost3000/first)
最终Link会编译成a标签,而to属性会被编译成 a标签的href属性
path属性:路由规则,这里需要跟Link组件里面to属性的值一致
component属性:展示的组件
定义项目使用路由,在入口文件/src/index.js文件中
3.在浏览器中输入后尝试匹配
使用Link或NavLink组件完成声明式导航的定义
Link/NavLink区别
如果当前的路由规则和Navlink中的To所写的规则一致则添加class样式,
在最上面要加exact,少用exact
react-router-dom中通过history对象中的push/replace/go等方法实现编程式导航功能。
编程式导航
路由参数:在Route定义渲染组件时给定动态绑定的参数。
React路由传参方式有三种:
以“/detail/:id”形式传递的数据
在落地组件中通过this.props.match.params得到
通过地址栏中的 ?key=value&key=value传递
在落地组件中通过this.props.location.search得到
通过路由对象中的state属性进行数据传递
在落地组件中通过this.props.location.state得到
在子里定义父路由的变量
render() {
// 获取前缀,供后续地址做路由拼接
let prefix = this.props.match.path;
return (
欢迎使用后台管理程序
);
}
!!!!!!!!!!! 或
path="/home" component={(router)=> { …router} />} />
router=> { …router} />} />
// 全匹配
router =>{ return
children渲染}} />
或
// 精确匹配 , 一般不用
} />
生命周期先是孩子后是老子
npm i -S react-transition-group
www就是classname
可控度不高
网址:Animate.css | A cross-browser library of CSS animations.
npm install animate.css --save
并不想让所有的路由都有动画效果,只是想对指定的页面有路由切换效果,可以利用高阶组件来完成。让组件有动画