日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

React学习分享(四)

發(fā)布時(shí)間:2023/12/20 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React学习分享(四) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

十、表單中的受控組件與非受控組件

1、非受控組件

React要編寫(xiě)一個(gè)非受控組件,可以使用ref來(lái)從DOM節(jié)點(diǎn)中獲取表單數(shù)據(jù),就是非受控組件。
例如:

import React, { Component } from 'react' export default class App extends Component {mytext = React.createRef()render() {return (<div><input type="text" ref={this.mytext} defaultValue="asdad" /><button onClick={() => { console.log(this.mytext.current.value); }}>獲取Value</button><button onClick={() => {this.mytext.current.value = ""}}>重置</button></div >)} }

因?yàn)榉鞘芸亟M件將真實(shí)數(shù)據(jù)儲(chǔ)存在DOM節(jié)點(diǎn)中,所以在使用非受控組件時(shí),有時(shí)候反而更容易同時(shí)集成 React 和非 React 代碼。如果你不介意代碼美觀性,并且希望快速編寫(xiě)代碼,使用非受控組件往往可以減少你的代碼量。否則,你應(yīng)該使用受控組件。

在 React 渲染生命周期時(shí),表單元素上的value將會(huì)覆蓋 DOM 節(jié)點(diǎn)中的值,在非受控組件中,你經(jīng)常希望React能賦予組件一個(gè)初始值,但是不去控制后續(xù)的更新。 在這種情況下, 你可以指定一個(gè)defaultValue屬性,而不是 value。(defaultValue是在非受控下使用,而value是在受控的時(shí)候使用)

同樣,checkbox radio支持defaultChecked,select和textarea支持defaultValue

1、受控組件

import React, { Component } from 'react' export default class App extends Component {state = {mytext: "123"}render() {return (<div><input type="text" value={this.state.mytext} onChange={(e) => {this.setState({mytext: e.target.value})}} /><button onClick={() => {console.log(this.state.mytext);}}>獲取Value</button><button onClick={() => {this.setState({mytext: ""})}}>重置</button></div>)} }

原理和vue的雙向數(shù)據(jù)綁定類(lèi)似(v-model)

由于在表單元素上設(shè)置了value屬性,因此顯示的值將始終為this.state.value ,這使得React的state成為唯一數(shù)據(jù)源。由于handlechange在每次按鍵時(shí)都會(huì)執(zhí)行并更新React的state,因此顯示的值將隨著用戶輸入而更新。

對(duì)于受控組件來(lái)說(shuō),輸入的值始終由React的state驅(qū)動(dòng)。你也可以將value 傳遞給其他UI元素,或者通過(guò)其他事件處理函數(shù)重置,但這意味著你需要編寫(xiě)更多的代碼。

注意: 另一種說(shuō)法(廣義范圍的說(shuō)法),React組件的數(shù)據(jù)渲染是否被調(diào)用者傳遞的props完全控制,控制則為受控組件,否則非受控組件。

十一、組件間通信

父子組件內(nèi)通信

  • 傳遞數(shù)據(jù)(父?jìng)髯?與傳遞方法(子傳父)
  • 父組件:

    import React, { Component } from 'react' import './css/01-maizuo.css' import Home from "./compontents/home" import Cinema from "./compontents/cinema" import My from "./compontents/My" import Tabbar from './compontents/Tabbar' import Navbar from './compontents/Navbar' export default class APP extends Component {state = {list: [{id: 0,text: "首頁(yè)"},{id: 1,text: "電影"},{id: 2,text: "我的"}],current: 0}switch() {switch (this.state.current) {case 0:return <Home></Home>case 1:return <Cinema></Cinema>case 2:return <My></My>default:return null}}render() {return (<div><Navbar event={this.tarrget} />{//表達(dá)式--支持函數(shù)表達(dá)式this.switch()}<Tabbar current={this.state.current} list={this.state.list} event={this.tarrget}></Tabbar></div>)}tarrget = (index) => {this.setState({current: index})} }

    子組件Tabbar:

    import React, { Component } from 'react' export default class Tabbar extends Component {render() {return (<div><div><ul>{this.props.list.map((item, index) =><li key={item.id} className={this.props.current === index ? 'active' : ''} onClick={() => this.click(index)}>{item.text}</li>)}</ul></div></div>)}click = (index) => {this.props.event(index)} }

    子組件Navbar:

    import React, { Component } from 'react' export default class Navbar extends Component {render() {return (<div><div style={{ background: "yellow", textAlign: "center", overflow: "hidden" }}><button style={{ float: "left" }}>back</button><span>賣(mài)座電影</span><button style={{ float: "right" }} onClick={() => this.goHome(0)}>home</button></div></div>)}goHome = (index) => {this.props.event(index)} }

    這里是父組件向子組件傳遞屬性,子組件通過(guò)回調(diào)函數(shù)返回返回值,采用的是受控的方式對(duì)子組件進(jìn)行控制,意思是在子組件中不過(guò)多的使用state狀態(tài),而是通過(guò)父組件的屬性進(jìn)行控制,減少組件內(nèi)的狀態(tài)。

    2.ref標(biāo)記 (父組件拿到子組件的引用,從而調(diào)用子組件的方法)
    代碼:

    import React, { Component } from 'react' export default class App extends Component {username = React.createRef()password = React.createRef()render() {return (<div><Field label="用戶名" type="text" ref={this.username}></Field><Field label="密碼" type="password" ref={this.password}></Field><button onClick={this.login}>登錄</button><button onClick={this.set}>設(shè)置登錄名</button><button onClick={() => {this.password.current.clear()this.username.current.clear()}}>取消</button></div>)}login = () => {console.log(this.username.current.state.value);console.log(this.password.current.state.value);}set = () => {this.username.current.setValue(123)} } class Field extends Component {state = {value: ""}clear = () => {this.setState({value: ""})}setValue = (value) => {this.setState({value: value})}render() {return (<div><label>{this.props.label}</label><input onChange={(e) => {this.setValue(e.target.value)}} value={this.state.value} type={this.props.type} /></div>)} }

    這里我們通過(guò)對(duì)子組件綁定ref 獲取組件中的狀態(tài)和方法,在父組件中進(jìn)行對(duì)狀態(tài)和方法的改變。類(lèi)似于面向?qū)ο蟮乃枷搿?/p>

    非父子組件內(nèi)通信

    1.狀態(tài)提升(中間人模式)

    React中的狀態(tài)提升概括來(lái)說(shuō),就是將多個(gè)組件需要共享的狀態(tài)提升到它們最近的父組件 上.在父組件上改變這個(gè)狀態(tài)然后通過(guò)props分發(fā)給子組件。總之就是,我們?cè)谔幚韮蓚€(gè)兄弟組件時(shí),可以通過(guò)回調(diào)的方式兄弟1組件把信息傳遞到父組件內(nèi),再通過(guò)props父組件傳遞到兄弟2組件,就可以收到信息了。

  • 發(fā)布訂閱模式實(shí)現(xiàn)
    首先我們先看這部分代碼(發(fā)布訂閱的核心代碼):
  • //調(diào)度中心 var bus = {list:[],//訂閱subscribe(callback){// console.log(callback)this.list.push(callback)},//發(fā)布publish(text){//遍歷所有的list, 將回調(diào)函數(shù)執(zhí)行// console.log(this.list)this.list.forEach(callback=>{callback && callback(text)})} }

    解讀代碼:我們?cè)谝粋€(gè)組件中訂閱一個(gè)消息通過(guò)回調(diào)函數(shù)的方式傳遞,把每次訂閱的回調(diào)放在一個(gè)全局變量數(shù)組中,在發(fā)布中,我們?nèi)ケ闅v這個(gè)數(shù)組,將里面的回調(diào)函數(shù)進(jìn)行執(zhí)行。
    案例:
    js:

    import React, { Component } from 'react' import axios from 'axios' //調(diào)度中心 var bus = {list:[],//訂閱subscribe(callback){// console.log(callback)this.list.push(callback)},//發(fā)布publish(text){//遍歷所有的list, 將回調(diào)函數(shù)執(zhí)行// console.log(this.list)this.list.forEach(callback=>{callback && callback(text)})} } export default class App extends Component {constructor(){super()this.state = {filmList:[],}axios.get(`/test.json`).then(res=>{console.log(res.data.data.films)this.setState({filmList:res.data.data.films})})}render() {return (<div>{/* {this.state.info} */}{this.state.filmList.map(item=><FilmItem key={item.filmId} {...item} ></FilmItem> )}<FilmDetail ></FilmDetail></div>)} } /*受控組件*/ class FilmItem extends Component{render(){// console.log(this.props)let {name, poster,grade,synopsis} = this.propsreturn <div className="filmitem" onClick={()=>{// console.log(synopsis)bus.publish(synopsis)}}><img src={poster} alt={name}/><h4>{name}</h4><div>觀眾評(píng)分:{grade}</div></div>} } class FilmDetail extends Component{constructor(){super()this.state = {info:""}bus.subscribe((info)=>{console.log("我再filmDetail中定義",info)this.setState({info:info})})}render(){return <div className="filmdetail">{this.state.info}</div>} }
  • context狀態(tài)樹(shù)傳參
  • import React, { Component } from 'react' import axios from 'axios' const GlobalContext = React.createContext() //創(chuàng)建context對(duì)象 export default class App extends Component {constructor(){super()this.state = {filmList:[],info:""}axios.get(`/test.json`).then(res=>{console.log(res.data.data.films)this.setState({filmList:res.data.data.films})})}render() {return (<GlobalContext.Provider value={{call:"打電話",sms:"短信",info:this.state.info,changeInfo:(value)=>{this.setState( {info:value})}}}><div>{/* {this.state.info} */}{this.state.filmList.map(item=><FilmItem key={item.filmId} {...item} ></FilmItem> )}<FilmDetail ></FilmDetail></div></GlobalContext.Provider>)} } /*受控組件*/ class FilmItem extends Component{render(){// console.log(this.props)let {name, poster,grade,synopsis} = this.propsreturn (<GlobalContext.Consumer>{(value)=>{console.log(value)return <div className="filmitem" onClick={()=>{console.log(synopsis)// this.props.onEvent(synopsis)// value.info = "2222222"// console.log(value)value.changeInfo(synopsis)}}><img src={poster} alt={name}/><h4>{name}</h4><div>觀眾評(píng)分:{grade}</div></div>}}</GlobalContext.Consumer>) } } class FilmDetail extends Component{render(){return (<GlobalContext.Consumer>{(value)=><div className="filmdetail">detail-{value.info}</div>}</GlobalContext.Consumer>)} }

    注意:GlobalContext.Consumer內(nèi)必須是回調(diào)函數(shù),通過(guò)context方法改變根組件狀態(tài)

    context優(yōu)缺點(diǎn): 優(yōu)點(diǎn):跨組件訪問(wèn)數(shù)據(jù) 缺點(diǎn):react組件樹(shù)種某個(gè)上級(jí)組件shouldComponetUpdate 返回false,當(dāng)context更新時(shí),不 會(huì)引起下級(jí)組件更新

    十二、插槽

    import React, { Component } from 'react' class Child extends Component{render(){return <div>child{/* 插槽 vue slot,具名插槽 */}{this.props.children[2]}{this.props.children[1]}{this.props.children[0]}</div>} } class Swiper extends Component{render(){return <div>{this.props.children}</div>} } export default class App extends Component {render() {return (<div><Swiper><div>111111</div><div>222222</div><div>333333</div></Swiper><Child><div>11111111</div><div>22222222</div><div>33333333</div></Child></div>)} }

    這里通過(guò)this.props.children來(lái)獲取寫(xiě)在組件里面的東西
    如果里面的東西想要獲取多個(gè)div,也可以寫(xiě)成數(shù)據(jù)this.props.children[0],this.props.children[1]這樣來(lái)得到,如果不寫(xiě)成數(shù)組this.props.children,則是獲得到全部的div。
    作用:

  • 為了復(fù)用
  • 一定程度減少父子通信。
  • 總結(jié)

    以上是生活随笔為你收集整理的React学习分享(四)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。