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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

React学习分享(四)

發布時間:2023/12/20 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 React学习分享(四) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

1、非受控組件

React要編寫一個非受控組件,可以使用ref來從DOM節點中獲取表單數據,就是非受控組件。
例如:

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 >)} }

因為非受控組件將真實數據儲存在DOM節點中,所以在使用非受控組件時,有時候反而更容易同時集成 React 和非 React 代碼。如果你不介意代碼美觀性,并且希望快速編寫代碼,使用非受控組件往往可以減少你的代碼量。否則,你應該使用受控組件。

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

同樣,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的雙向數據綁定類似(v-model)

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

對于受控組件來說,輸入的值始終由React的state驅動。你也可以將value 傳遞給其他UI元素,或者通過其他事件處理函數重置,但這意味著你需要編寫更多的代碼。

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

十一、組件間通信

父子組件內通信

  • 傳遞數據(父傳子)與傳遞方法(子傳父)
  • 父組件:

    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: "首頁"},{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} />{//表達式--支持函數表達式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>賣座電影</span><button style={{ float: "right" }} onClick={() => this.goHome(0)}>home</button></div></div>)}goHome = (index) => {this.props.event(index)} }

    這里是父組件向子組件傳遞屬性,子組件通過回調函數返回返回值,采用的是受控的方式對子組件進行控制,意思是在子組件中不過多的使用state狀態,而是通過父組件的屬性進行控制,減少組件內的狀態。

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

    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}>設置登錄名</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>)} }

    這里我們通過對子組件綁定ref 獲取組件中的狀態和方法,在父組件中進行對狀態和方法的改變。類似于面向對象的思想。

    非父子組件內通信

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

    React中的狀態提升概括來說,就是將多個組件需要共享的狀態提升到它們最近的父組件 上.在父組件上改變這個狀態然后通過props分發給子組件。總之就是,我們在處理兩個兄弟組件時,可以通過回調的方式兄弟1組件把信息傳遞到父組件內,再通過props父組件傳遞到兄弟2組件,就可以收到信息了。

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

    解讀代碼:我們在一個組件中訂閱一個消息通過回調函數的方式傳遞,把每次訂閱的回調放在一個全局變量數組中,在發布中,我們去遍歷這個數組,將里面的回調函數進行執行。
    案例:
    js:

    import React, { Component } from 'react' import axios from 'axios' //調度中心 var bus = {list:[],//訂閱subscribe(callback){// console.log(callback)this.list.push(callback)},//發布publish(text){//遍歷所有的list, 將回調函數執行// 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>觀眾評分:{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狀態樹傳參
  • import React, { Component } from 'react' import axios from 'axios' const GlobalContext = React.createContext() //創建context對象 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>觀眾評分:{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內必須是回調函數,通過context方法改變根組件狀態

    context優缺點: 優點:跨組件訪問數據 缺點:react組件樹種某個上級組件shouldComponetUpdate 返回false,當context更新時,不 會引起下級組件更新

    十二、插槽

    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>)} }

    這里通過this.props.children來獲取寫在組件里面的東西
    如果里面的東西想要獲取多個div,也可以寫成數據this.props.children[0],this.props.children[1]這樣來得到,如果不寫成數組this.props.children,則是獲得到全部的div。
    作用:

  • 為了復用
  • 一定程度減少父子通信。
  • 總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。