React组件的创建与state同步异步详解
作者:旺仔好吃糖
组件的创建
类组件
类组件是指使用ES6中class定义的组件称为类组件
导入类组件时 组件名首字母必须大写
类组件必须要继承React.Component父类(相关方法和属性均会被继承)
render为固定函数(必须有),有返回值,返回类组件的结构(jsx)
🏸定义类组件并暴露
import React from 'react' //App为类名 可随意起 继承 React.Component(固定,不可丢掉) class App extends React.Component{ render(){ render(){ //1.return若要回车必须加上() //2.最外层只能有一个标签,不能有兄弟并列 return ( <section> hello react <ul> <li>1111</li> <li>222</li> </ul> <div>新的内容111</div> <div>新的内容2222</div> </section> ) } } } export default App //导出:方便被其他组件引用
🏸在src下的 index.js入口文件中导入 需要的App类组件
React 17之前版本 import React from 'react' import ReactDOM from 'react-dom' import App from "./01-base/01-class组件" //引入时必须大写 ReactDOM.render(<App></App>,document.getElementById("root")) ...................................... React 18版本 import {createRoot} from 'react-dom/client' import App from "./01-base/01-class组件" //导入App组件 const container = document.getElementById('root') const root = createRoot(container); //App放入的位置 root.render(<App/>) //单双标签均可以
函数式组件
function App(){ return ( <div> hello functional component <div>111</div> <div>2222</div> </div> ) } export default App
组件的嵌套
import React, { Component } from 'react' class Child extends Component{ render(){ return <div>child</div> } } class Navbar extends Component{ render(){ return ( <div> navbr <Child></Child> </div> ) } } function Swiper(){ return <div>swiper</div> } const Tabbar = ()=> <div>tabbar</div> //以上3种子组件的形式 均可进行嵌套 export default class App extends Component { render() { return ( <div> <Navbar></Navbar> <Swiper></Swiper> <Tabbar></Tabbar> </div> ) } } ........................................ import App from "./01-base/03-组件的嵌套" import {createRoot} from 'react-dom/client' const container = document.getElementById('root') const root = createRoot(container); root.render(<App/>)
组件的样式
推荐使用行内样式,因为React觉得每个组件都是一个独立的整体
行内样式
想给虚拟dom添加行内样式,需要使用表达式传入样式对象的方式来实现
render() { var myname = 'xiaoming' var isChecked = false var obj = { backgroundColor:"yellow", fontSize:""//驼峰命名法 } return ( <div> {myname}-{10+20}-岁 {10>20?"a":"b"} <div style={obj}>111</div> <div style={style={{textDecoration:isChecked?"line-through":''}}> //这里有两个括号,第一个表示我们再要JSX里插入了JS了,第二个是对象的括号 <div style={{background:"red"}}>222</div> </div> ) }
🔎1. {}里面为js表达式,不支持语句
🔎2. 行内样式需要写入一个样式对象如上面的obj,这个样式对象的位置可以放在很多地方,例如render函数里、组件原型上、外链js文件中
class样式
- css文件中写入样式
- 导入css文件
- 为元素添加class类名(class需要写成className,在写类js代码,会受到js规则的存在,而class为关键字)
<div className="active">333</div> <div id="myapp">444</div>
⭐️⭐️ ⭐️ class ==> className,for ===> htmlFor(label) ⭐️⭐️ ⭐️
<label htmlFor='username'>用户名:</label> <input type="text" id="username"></input>
事件处理
事件绑定
📢render内使用箭头函数— 直接使用this
a = 100 render(){ return( <button onClick={ ()=>{ console.log("click1","如果处理逻辑过多不推荐",this.a); } }>add1</button> ) }
箭头函数作用域为App,所以this直接为App
📢render内调用函数,函数普通函数 – 使用bind改变this指向
a = 100 render(){ return( {/* call,apply改变this指向并自动执行函数;bind改变this指向不自动执行 */} <button onClick={ this.handleClick2.bind(this)}>add2-不推荐</button> ) } handleClick2(){ console.log("click2",this.a) }
render内刚开始 this 为 undefined,通过使用 bind 将this指向改为App
📢render内调用函数,函数箭头函数 – 直接使用this
a = 100 render(){ return( <button onClick={ this.handleClick3 }>add3-比较推荐</button> ) } handleClick3 = ()=>{ console.log("click3",this.a) }
📢render内使用箭头函数调用函数 – 直接使用this
a = 100 render(){ return( {/* 非常推荐 */} <button onClick={ ()=>{ this.handleClick4() } }>add4</button> {/* 执行匿名函数后调用handleClick4 */} ) } handleClick4 = ()=>{ console.log("click4",this.a) }
onClick里面的this为App,所以当handleClick被调用时不论是箭头函数还是普通函数this均和调用者相同都为App
事件的参数传递
🎐1. 在render里调用方法的地方外面包一层箭头函数
🎐2. 在render里通过this.handleClick.bind(this,参数)来传递
🎐3. 通过event传递
ref的应用
📌给标签设置ref=“mytext”
<input ref="mytext"></input> <button onClick={ ()=>{ console.log("click1",this.refs.mytext.value); } }>add1</button>
通过 this.refs.mytext,ref可以获取到应用的真实dom
📌 给组件设置ref="username
通过这个获取 this.refs.username ,ref可以获取到组件对象
📌新的写法(严格模式下)
myref = React.createRef() <input ref={this.myref}></input> <button onClick={ ()=>{ console.log("click",this.myref.current.value); } }>add1</button>
访问 this.myref.current
状态(state)
状态就是组件描述某种显示情况的数据,由组件自己设置和更改,也就是说组件自己维护,使用状态的目的就是为了在不同的状态下是组建的显示不同(自己管理)
定义state
state={ mytext:"收藏", myShow:true } render(){ return( <div> <h1>welcome</h1> <button onClick={()=>{ //this.state.mytext = "取消收藏" 不用直接修改state }}>{this.state.mytext}</button> </div> ) }
this.state是纯js对象,在vue中,data属性利用Object.defineProperty处理过的,更改data的数据的时候回出发数据的getter和setter,但是React中没有这样的处理,如果直接更改,react无法得知,所以需要使用setState间接修改
setState
myShow存放在实例的state对象当中,组件的render函数内,会根据组件的state的中的myShow不同 显示“取消”或“收藏”
可以一次更新多个状态
import React, { Component } from 'react' export default class App extends Component { // state={ // mytext:"收藏", // myShow:true // } constructor(){ super()//必须写 this.state={ mytext:"收藏", myShow:true, myName:"xiaoming" } } // !!!!以上两种state写法均可以!!! render() { return ( <div> <h1>welcome--我的名字是{this.state.myName}</h1> <button onClick={()=>{ //this.state.mytext = "取消收藏" 不用直接修改state this.setState({ //mytext:"取消收藏" myName:'zhangsan', myShow:!this.state.myShow })//间接修改state if(this.state.myShow){ console.log("收藏逻辑"); }else{ console.log("取消逻辑"); } }}>{this.state.myShow?'收藏':'取消收藏'}</button> </div> ) } }
setState同步异步
- setState处在同步的逻辑中,异步更新状态,更新真实dom
- setState处在异步的逻辑中,同步更新状态,同步更新真实dom
- setState接受第二个参数,第二个参数回调函数,状态和dom更新后就会被触发
补充-React面试题
react事件绑定和普通事件绑定的区别
React并不会真正的绑定事件到每一个具体的《》元素上,而是采用事件代理的模式,绑定在根节点身上
Event对象
和普通浏览器一样,事件handler会被自动传入一个event对象,这个对象和普通的浏览器event对象所包含的方法和属性基本一致。不同的是React中的event对象并不是浏览器提供的,而是自己内部构建的。他同样具有event.stopPropagation、event.preventDefalut这种常用方法
到此这篇关于React组件的创建与state同步异步详解的文章就介绍到这了,更多相关React组件的创建内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!