React
React与Vue的不同之处(重要)
1.组件化方面,react使用jsx,一个js文件就是一个组件,而vue使用的是单文件组件
2.数据流方面,react完全遵循单向数据流的原则,vue理论上也是单向数据流,但是没有react严格,vue是可以双向数据绑定的
3.语法方面,react使用jsx
4.vue是响应式编程,react是函数式编程
5.两者的diff算法不同,react用的算法是fiber(vue3.0)算法比react快
6.在react中,有纯函数的概念
7.vue是一个渐进式的框架
8.react的元素(对象)创建出来是不允许改变的,只能通过新的值来覆盖
创建项目
在vscode的settings.json文件中粘贴下面的代码
"emmet.includeLanguages": {
"vue-html": "html",
"vue": "html",
"javascript": "javascriptreact"
}
使用npx创建项目
npx create-react-app my-app
npm start
//相当于
cnpm i create-react-app -g
create-react-app my-app
在package.json文件中设置启动项目命令
全局安装npx(一个包管理工具,不同于npm全局安装的文件会存储的电脑硬盘里面,而npx在使用完成后自动删除安装包)
npm i npx -g
如果安装不上npx那么全局安装create-react-app
npm i create-react-app -g
使用全局create-react-app创建项目
create-react-app 项目名字
react文件介绍&关键指标
项目创建好之后里面会有一些默认的文件,node_modules是包,
public文件夹中的manifest.json是关于移动端的一些配置
src文件夹中的reportWebVitals.js是关于网站指标的
setupTests.js是用于缓存的
新增网站重要指标web-vitals
LCP(largest contentful paint):评估页面主要内容可能已完成加载时的感知加载速度
FID(first input delay):首次输入延迟评估用户首次与网页交互时的网页相应速度
CLS(cumulative layout shift):累计布局偏移评估可见页面内容的视觉稳定性
创建组件&注意细节
组件的首字母必须大写
元素的首字母必须小写
JSX
jsx运行时需要babel进行编译
react元素并不是真正的html元素,而是对象
react对象不可变
传值
<Com name="宋亚轩"/>
function Com(props){
return (
<fieldset>
<legend>jsx</legend>
<h1>{props.name}</h1>
</fieldset>
)
}
export default Com
组件提取
function Comment(props) {
return (
<div className="Comment">
<div className="UserInfo">
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{props.date}
</div>
</div>
);
}
改造成
function Avatar(props){
return (
<img className="Avatar"
src={props.author.avatarUrl}
alt={props.author.name}
/>
)
}
function UserInfo(props){
return (
<div className="UserInfo">
<Avatar author={props.author}/>
<div className="UserInfo-name">
{props.author.name}
</div>
</div>
)
}
function Comment(props) {
return (
<div className="Comment">
<UserInfo author={props.author}/>
<div className="Comment-text">
{props.text}
</div>
<div className="Comment-date">
{props.date}
</div>
</div>
);
}
export default Comment
改造tick案例
//将函数转换成类
// 1. 创建一个名称扩展为 React.Component 的ES6 类
// 2. 创建一个叫做render()的空方法
// 3. 将函数体移动到 render() 方法中
// 4. 在 render() 方法中,使用 this.props 替换 props
// 5. 删除剩余的空函数声明
import React from 'react'
class Tick extends React.Component{
constructor(){
super()//因为使用了extends所以必须使用super
this.state = {//添加一个局部状态
timer:new Date().toLocaleTimeString()
}
}
changeState(){
//设置一个定时器,每秒调用一次
this.interval = setInterval(()=>{
//改变状态
this.setState({
timer:new Date().toLocaleTimeString()
})
},1000)
}
//钩子函数
componentDidMount(){//组件已经挂载
//当组件挂载 调用函数 更新时间
this.changeState()
}
componentWillUnmount(){//组件即将卸载
//当组件即将卸载 清除定时器
clearInterval(this.interval)
}
render(){//钩子函数 进行diff算法 更新虚拟dom
return (
<fieldset>
<legend>时间嘀嗒嘀嗒地过去了</legend>
<h1>北京时间:</h1>
<h1>{this.state.timer}</h1>
</fieldset>
)
}
}
定义默认props
1.给组件定义默认的props属性
const comment={name:"小明"}
Comment.defaultProps=comment;//设置默认的props
2.在组件中使用静态属性static定义
class A extends React.Component{
constructor(){
super()
this.state={}
}
static defaultProps = {//使用关键字static定义
name:"小明"
}
}
props的只读性
纯函数:不修改自身输入值的函数
非纯函数:修改自身输入值的函数
使用组件时一定要像纯函数那样使用
props是只读的,如果修改会报错
但是其实也可以更改
const Child = props => {
console.log(props.gift.name);//输出 宋亚轩
props.gift.name = "爆米花"//最后展示的是 爆米花
return (
<h1>{props.gift.name}</h1>
)
}
const Parent = props => {
return (
<Child gift={{name:"宋亚轩"}}/>
)
}
export default Parent
原因:react只会进行浅比较,传递引用数据类型时,虽然更改了属性但是地址没有发生变化
回顾类
class parent{
constructor(name,age,hobby){//构造器
this.name = name;
this.age = age;
this.hobby = hobby
}
static setTick(){//静态方法 和类一起被创建 实例化之后会被标记为“封闭”
console.log("滴答滴答");//获取不到this 因为被创建时还没有实例化
}
sayHi(){//动态方法 实例化之后才能调用 否则报错
console.log("sayHi");//实例化之后this才会正确指向当前实例
}
}
//实例化
// let p1 = new parent("宋亚轩",17,"唱歌")
// console.log(p1);
// p1.sayHi()
// class child extends parent{}
// let c1 = new child()
// console.log(c1);//child { name: undefined, age: undefined, hobby: undefined }
// class child extends parent{
// constructor(){//当使用了extends关键字并且子类用了自己的构造器
// //就必须调用super()
// super()
// this.salary="14k"
// }
// }
// let c1 = new child()
// console.log(c1);
// 输出:child {
// name: undefined,
// age: undefined,
// hobby: undefined,
// salary: '14k'
// }
class child extends parent{
constructor(){
super("宋亚轩",17,"唱歌")//调用super()就相当于调用了父类的构造函数
//super的作用:让子类获取正确的this指向,不允许在使用super之前调用this
// console.log(super.age);//undefined
super.sayHi()//sayHi super可以调用父类的动态方法
this.sayHi()//sayHi this指向子实例
//this的特点:谁调用就指向谁
this.salary="14k"
}
}
let c1 = new child()
console.log(c1);//child { name: '宋亚轩', age: 17, hobby: '唱歌', salary: '14k' }