开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
临近年关,公司的活也不多了,之前一直用的vue,现在开始偷偷学习react,为明年跑路做准备,一边学习一边记录笔记。
JSX
JSX就是Javascript和XML结合的一种格式。React发明了JSX,可以方便的利用HTML语法来创建虚拟DOM,当遇到 <
,JSX就当作HTML解析,遇到 {
JavaScript解析.
jsx语法规则
- 定义虚拟DOM时,不要写引号
- 标签中混入js表达式要用{}
- 样式的类名指定不要用
class
,要用className
- 内联样式,要用
style={{key:value}}
形式去写 - 只有一个根标签
- 标签必须闭合
- 标签首字母
-
- 若小写字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错
- 若大写字母开头,react就去渲染对应的组件,若组件没有定义,则报错
class
类名
return(
<div className="title">
{/* 这里的class类名应该写为className */}
</div>
)
label
中的for
return(
<label htmlFor="idName">名字</label>
{/* 这里的label中的for应该写为htmlFor */}
<input id="idName" />
)
解析html标签
return(
<div>
<div
dangerouslySetInnerHTML={{__html:item}}
></div>
</div>
)
// 不推荐这样写
{}
里边只能写js表达式不能写js语句(代码)
- 表达式 一个表达式会产生一个值,可以在任何一个需要值的地方
-
- a
- a + b
- demo(1)
- arr.map()
- function test(){}
- 语句(代码)
-
- if(){}
- for(){}
- switch(){ case:xxx}
模块
- 向外提供特定功能的js程序,一般就是一个js文件
- 为什么要拆成模块:随着业务逻辑增加,代码越来越多且复杂。
- 作用:复用js,简化js的编写,提高js运行效率
组件
- 用来实现局部功能效果的代码和资源的集合(html/css/js/images等等)
- 为什么:一个界面的功能更复杂
- 作用:复用编码,简化项目编码,提高运行效率
模块化
当应用的js都以模块来编写的,这个应用就是一个模块化的应用
组件化
当应用是以多组件的方式实现,这个应用就是一个组件化的应用。
class类组件
import React from 'react'
class App extends React.Component{
render() {
return (
<div>测试123</div>
)
}
}
export default App
函数组件
function App() {
return (
<div>测试函数商城</div>
)
}
export default App
组件嵌套
import React, { Component } from 'react'
// 父组件
export default class App extends Component {
render() {
return (
<div>
<Nav>1</Nav>
<Swiper>2</Swiper>
<Tabbar>3</Tabbar>
</div>
)
}
}
// Nav组件
export default class Nav extends Component{
render() {
return (
<div>Nav组件</div>
)
}
}
// Swiper组件
function Swiper(){
return (
<div>Nav组件</div>
)
}
// Tabbar组件
const Tabbar = ()=><div>Tabbar组件</div>
import { Component } from "react";
export default class Test extends Component {
render() {
var aa = 123;
return (
<div>
测试123
<div
onClick={() => {
console.log("Ceshi"); // 这种写法不推荐 但可以访问到this
}}
>
{aa}
</div>
<button onClick={this.handleBtn}>点击</button>
<button onClick={this.handleBtn2}>点击2</button>
<button onClick={()=>this.handleBtn3()}>点击3</button>
</div>
);
}
// 第一种写法 访问不到this,打印undefined 可以通过this.handleBtn.bind(this)访问
handleBtn() {
console.log("点击按钮了",this);
}
// 第二种写法 这种可以访问到this
handleBtn2 = () => {
console.log("点击按钮了2");
}
// 第三种写法 可以访问到this,比较推荐这种写法
handleBtn3(){
console.log("点击按钮了333");
};
}
react并不会真正的绑定事件到每一个具体的元素上,而是采用事件代理的模式
Context
context相当于一个公共的存储空间,可以将多个组件中都需要访问的数据同意存储到一个Context中,这样就无需通过props逐层传递,即可使组件访问到这些数据。
import React from 'react';
const TestContext = React.createContext({name:"小明",age:20});
export default TestContext
// 方式一
// 需要用到的文件中
// 使用方式
// 1. 引入Context
// 2. 使用xxx.Consumer 组件来创建元素
// 3. Consumer的标签体需要一个回调函数,它会将Context设置为回调函数的参数,
// 通过参数就可以访问到存储的数据。
import React from 'react';
import TestContext from "./store/TestContext"
const A = ()=>{
return(
<TestContext.Consumer>
{(ctx)=>{
return <div>
{ctx.name} - {ctx.age}
</div>
}}
</TestContext.Consumer>>
)
}
// 方式二 钩子函数
const B = ()=>{
const ctx = useContext(TestContext)
return(
<div>{ctx.name}-{ctx.age}</div>
)
}
import TestContext from "./store/TestContext"
const App = ()=>{
return(
<TestContext.Provider value={{name:"修改的数据",age:100}}>
<div>
<A/>
<B/>
</div>
</TestContext.Provider>
)
}
注意:通过数据的生产者,可以使用它来指定Context中的数据,通过value来指定Context中存储的数据,在该组件的所有子组件中都可以通过Context来访问它所指定数据。
通过Context访问数据时,会读取离它最近的Provider中的数据,若没有Provider,则读取Context中的默认数据。
常用的hooks
useState
当直接在函数体中调用setState时,就会陷入死循环。
当新的state值和旧值相同时,它是不会触发组件的重新渲染的。但如果是渲染阶段,是不会检查state值是否相同的。如果不是渲染阶段,会检查state的值是否相同,如果值不相同,则对组件进行重新渲染,如果值相同,则不对组件重新渲染。
如果值相同,React在一些情况下会继续执行当前组件的渲染,但是这个渲染不会触发其子组件的渲染,这次渲染不会产生实际的效果。这种情况通常发生在值第一次相同时。
useEffect
useEffect()是一个钩子函数,需要一个函数作为参数。
这个作为参数的函数,将会在组件渲染完毕后执行。
在开发中,可以将那些会产生副作用的代码编写到useEffect的回调函数中,这样可以避免这些代码影响到组件的渲染。
默认情况下useEffect中的函数会在每次组件渲染完成后都会调用。
useEffect()中可以传入第二个参数,第二个参数是数组,在数组中可以指定Effect的依赖项。指定后,只有当依赖发生变化时Effect才会触发。
通常会将Effect中使用的所有的变量都设置为依赖项,这样一来可以确保这些值发生变化时,会触发Effect的执行。
如果依赖项是空数组,意味着Effect只会在组件初始化的时候只执行一次。
清理函数:
useEffect(()=>{
const timer = setTimeout(()=>{
console.log('触发了')
},1000)
// 在Effect的回调函数中,可以指定一个函数作为返回值
// 这个函数可以称其为清理函数,它会在下次Effect执行前调用。
// 可以在这个函数中,做一些工作来清除上次Effect执行所带来的的影响
return ()=>{
clearTimeout(timer)
}
})