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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

react方法返回html_React全家桶之React基础(推荐新手必看)

發布時間:2023/12/10 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 react方法返回html_React全家桶之React基础(推荐新手必看) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

學習目標

  • 安裝create-react-app腳手架
  • 熟練React基礎語法
  • 掌握JSX語法
  • 掌握setState
  • 掌握React生命周期
  • 掌握props傳遞參數
  • 掌握React組件通信

資源

  • react
  • create-react-app

起步

上手

  • npm i -g create-react-app 安裝官方腳手架
  • create-react-app 01_react 初始化
  • react的api比較少,基本學習一次,就再也不用再看文檔,它的核心是JS

React&ReactDOM

React只做邏輯層,reactDOM去渲染真實的DOM

刪除src下面所有代碼,新建index.js

import React from 'react'; import ReactDOM from 'react-dom'; import App from './App' ReactDOM.render(<App />,document.querySelector('#root'))

新建 App.js

import React from 'react' class App extends React.Component {render() {return (<div>hello,小馬哥</div>)} } export default App;

以上代碼感覺都沒有問題,但是發現了一個很有趣的標簽語法,它既不是字符串也不是HTML

它被稱為JSX,是一個JavaScript的語法擴展.我們建議在 React 中配合使用 JSX,JSX 可以很好地描述 UI 應該呈現出它應有交互的本質形式。JSX 可能會使人聯想到模版語言,但它具有 JavaScript 的全部功能。

JSX

在JavaScript中直接寫的標簽,是一個JSX(JS+XML,由于HTML也是XML的一種,可以認為JS+HTML)元素,也是一個react元素,這個元素實際是一個對象,就是虛擬DOM元素

React 認為渲染邏輯本質上與其他 UI 邏輯內在耦合.比如,在 UI 中需要綁定處理事件、在某些時刻狀態發生變化時需要通知到 UI,以及需要在 UI 中展示準備好的數據。

import React, { Component } from 'react'import logo from './favicon.ico' const ele = <h2>hello,world</h2> function formatName(user) {// 也可以是個表達式return user.firstName + '' + user.lastName; } const user = {firstName: '張',lastName: '三豐' }//jsx也可以是表達式 function getGreeting(user) {if (user) {return <h1>hello {formatName(user)}</h1>}return <h1>hello,小馬哥</h1> } export default class App extends Component {render() {return (<div>{ele}{/* jsx運算 */}{2 + 1}<br />{/*jsx嵌入表達式*/}{formatName(user)}{/* 添加屬性 */}<img src={logo} alt="" /></div>// getGreeting())} }

強烈建議大家閱讀官網,針對React.render()內部的實現操作

元素渲染

元素是構成React應用的最小磚塊,比如:const ele = <h1>hello,world</h1>

與瀏覽器的 DOM 元素不同,React 元素是創建開銷極小的普通對象。React DOM 會負責更新 DOM 來與 React 元素保持一致

上節課的ReactDOM.render()其實就是在渲染DOM節點

更新已渲染的元素

React元素是不可變對象,一旦被創建,無妨更改它的子元素或者屬性

計時器的例子

function tick() {const element = (<div><h1>Hello, world!</h1><h2>{new Date().toLocaleTimeString()}.</h2></div>);ReactDOM.render(element, document.querySelector('#root')); }setInterval(tick, 1000);

大多數情況下,React應用只會調用一次ReactDOM.render()

React只需要更新它需要更新的部分

React DOM會將元素和它的子元素與它們之前的狀態進行比較,并只會進行必要的更新來使DOM達到預期的狀態

循環綁定元素

當數據從后端請求回來之后,在React中,一般都需要循環綁定元素

map綁定

在React中,循環綁定元素都是使用map方法,不能使用forEach是因為forEach沒有返回值

let ul = (<ul>{ arr.map((item, index)=>{return <li key={index}>{item}</li>}) } </ul>);

結果會是一個 JSX 元素組成的數組,放入頁面中,不會使用逗號分隔開。

循環綁定的 JSX 元素,必須要有 key 屬性,來區分不同的元素,否則會報錯。

過濾元素

同樣通過map方法,只要把不符合條件的元素,返回為null即可,原因在于,null會被表示為空.如果使用filter,那么就沒有辦法對元素進行處理,只能過濾,還是需要使用map進行處理

let ul = (<ul>{ arr.map((item, index)=>{return (item.price < 1000 ? null : <li key={index}>{item}</li>;)}) } </ul>)

ref和refs

在React中,類似于Vue,可以通過ref標記元素,然后通過this.refs獲取元素,只是Vue中使用的是this.$refs獲取元素

字符串寫法

通過設置一個字符串值來標記元素,然后通過這個字符串作為屬性獲取元素

class Input extends Component {handleChange = (e) => {console.log(this.refs.a.value)}render() {return (<div><input type="text" ref="a" onChange={this.handleChange} /></div>)} }

函數寫法

函數作為一個ref的屬性值,這個函數接受一個參數,就是真實的DOM元素

可以把這個元素掛載到實例上,方便后面的操作

class Input extends React.Component {componentDidMount() {console.log(this.a); //獲取真實的DOM元素}render() {return (<div><input type="text" ref={x=>this.a = x}/> </div>);} }

組件&props

React創建組件有來兩種方式

  • 函數聲明
  • 類聲明

React組件特點:

  • 組件名稱應該首字母大寫,否則會報錯
  • 組件定義之后,可以像JSX元素一樣使用
  • 必須使用render函數才能將虛擬DOM渲染成真實的DOM
  • 使用組件時,可以使用單標簽,也可以使用雙標簽

函數組件

組件,從概念上類似于 JavaScript 函數。它接受任意的入參(即 “props”),并返回用于描述頁面展示內容的 React 元素。

  • 函數聲明的組件,必須返回一個JSX元素
  • 可以通過屬性給組件傳遞值,函數通過props參數屬接收

定義組件最簡單的方式就是編寫JavaScript函數

function Welcome(props){return <h2>hello,{props.name}</h2> }

我們稱為該組件為"函數組件",因為它本質上就是一個函數

類聲明組件

使用ES6的class的方式定義組件

類聲明組件需要注意

  • 在React中有一個屬性Component,是一個基類,使用類聲明組件時,必須繼承這個基類
  • 在類中,必須有render函數,constructor不是必須的
  • 在render函數中**,需要return一個JSX元素**
class Welcome extends Component {render() {return (// 它會將 JSX 所接收的屬性(attributes)轉換為單個對象傳遞給組件,這個對象被稱之為 “props”。<h2>Welcome,{this.props.name}</h2>);} }注意: 組件名稱必須以大寫字母開頭。 React會將小寫字母開頭的組件稱之為標簽
例如,<div />代表HTML的div標簽,而<Welcome />則代表一個組件,并且需在作用域內使用Welcome

兩種方式的區別

真實項目中,都只使用class定義組件

  • class定義的組件中有this,狀態,生命周期
  • function聲明都沒有

組合組件

組件可以輸出的時候嵌入其他的組件。這就可以讓我們用同一組件中來抽離出任意層次的細節(復用組件)。按鈕,表單,對話框,甚至整個屏幕的內容:在 React 應用程序中,這些通常都會以組件的形式表示。

什么是復合組件:

  • 將多個組件進行組合,例如調用兩次相同的組件
  • 結構非常復雜時需要將組件拆分成小組件
  • 會存在父子關系的數據傳遞
import React, { Component } from 'react'; import ReactDOM from 'react-dom';class Welcome extends Component {render() {return (<div><h3>Welcome,{this.props.name}</h3></div>);} } class App extends Component {render() {return (<div><Welcome name='張三'></Welcome><Welcome name='李四'></Welcome><Welcome name='王五'></Welcome></div>)} } // 組合組件 ReactDOM.render(<App></App>,document.querySelector('#root'));

可想而知,React開發其實就是組件化開發,因為React真的是組件化開發的鼻祖

提取組件

將組件拆分成更小的組件

import React, { Component } from 'react'; import ReactDOM from 'react-dom';// 所有props是只讀的,不能直接修改 class Avatar extends Component {render() {return (<img src={this.props.user.avatarUrl} alt={this.props.user.name} />);} }class UserInfo extends Component {constructor(props) {super(props);console.log(this.props);}render() {return (<div className="userinfo"><Avatar user={this.props.user}></Avatar><div className='username'><h3>{this.props.user.name}</h3></div></div>);} }class Comment extends Component {constructor(props) {super(props);}render() {return (<div className='comment'><UserInfo user={this.props.user}></UserInfo><div className="Comment-text">{this.props.user.text}</div><div className="Comment-date">{this.props.user.date}</div></div>);} } class App extends Component {constructor() {super();this.user = {avatarUrl: 'https://hcdn1.apeland.cn/media/course/icon2.png',name: '張三',text: "hello,React component",date: new Date().toLocaleString()}}render() {return (<div><Comment user={this.user}></Comment></div>)} } // 組合組件 ReactDOM.render(<App></App>,document.querySelector('#root'));

最初看上去,提取組件可能是一件繁重的工作,但是,在大型應用中,構建可復用組件庫是完全值得的。 根據經驗來看,如果 UI 中有一部分被多次使用(Button,Panel,Avatar),或者組件本身就足夠復雜(App,Comment),那么它就是一個可復用組件的候選項。你說對吧!
父子組件通信

父傳子

父組件通過行間屬性傳遞數據到子組件,子組件通過實例上的props屬性接收新的數據

React 的數據是單向數據流,只能一層一層往下傳遞。當組件的屬性發生改變,那么當前的視圖就會更新

子傳父

通過給子組件傳遞一個函數,子組件調用父親的函數將值作為參數傳遞給父組件,父組件更新值,刷新視圖。

父組件中定義一個函數,通過屬性傳遞給子組件。

這個傳遞的函數必須是一個箭頭函數import React, { Component } from 'react'; import ReactDOM from 'react-dom';class ChildCom extends Component {constructor(props) {super(props);console.log(props);this.state = {val:''}this.handlerClick = this.handlerClick.bind(this);this.handlerChange = this.handlerChange.bind(this);}handlerChange(event){this.setState({val: event.target.value})}handlerClick(){if(this.state.val){this.props.addHandler(this.state.val);// 清空輸入框this.setState({val: ''})}}render() {return (<div><input type="text" value = {this.state.val} onChange = {this.handlerChange}/><button onClick={this.handlerClick}>添加</button>{this.props.menus.map((item,index) => {return <p key = {index}>{item}</p>})}</div>);} }class App extends Component {constructor(props) {super(props);this.state = {menus: ['烤腰子', '辣炒雞丁', '炸黃花魚']}}// 一定要使用箭頭函數addHandler = (val)=>{this.state.menus.push(val);this.setState({menus:this.state.menus})}render() {// 修改狀態之后,會重新調用renderreturn (<div><ChildCom menus={this.state.menus} addHandler = {this.addHandler}></ChildCom></div>);} }ReactDOM.render(<App />, document.querySelector('#root'));

Props的只讀性

組件無論是使用函數聲明還是通過 class 聲明,都決不能修改自身的 props

//該函數不會嘗試更改入參,且多次調用下相同的入參始終返回相同的結果。 function sum(a, b) {return a + b; } //它更改了自己的入參 function withdraw(account, amount) {account.total -= amount; }

所有 React 組件都必須像純函數一樣保護它們的 props 不被更改。

state

組件狀態

組件中數據的來源

  • 屬性:是由外接傳遞過來的
  • 狀態:是自己的,只能通過setState來改變狀態
只有類聲明的組件中,才有狀態

修改狀態

除了constructor之外的其它地方,如果需要修改狀態,都只能通過this.setState方法
這個方法傳入的第一個參數,可以是一個對象,也可以是一個函數

  • 是一個對象,這個對象中包含需要改變的屬性,它會與原有的狀態進行合并
  • 是一個函數,接收第一個參數是 prevState,上一個狀態對象,第二個參數是 props

這個方法的第二個參數,是一個回調函數,在狀態改變之后執行。
如果下一個狀態依賴于上一個狀態,需要寫成函數的方式

關于setState

  • 在 react 組件的生命周期或事件的綁定中,setState 是異步的
  • 在定時器或原生的事件中,setState 不一定是異步的
// state.count 當前為 0 componentDidMount(){this.setState({count: this.state.count + 1});console.log(this.state.count) } // 輸出 0

在元素渲染章節中,我們只了解了一種更新 UI 界面的方法。通過調用 ReactDOM.render() 來修改我們想要渲染的元素

function tick() {const element = (<div><h1>Hello, world!</h1><h2>{new Date().toLocaleTimeString()}.</h2></div>);ReactDOM.render(element, document.querySelector('#root')); }setInterval(tick, 1000);

本節學習如何封裝真正可復用的Clock組件

import React, { Component } from 'react'; import ReactDOM from 'react-dom';// 學習如何封裝真正可復用的Clock組件。 class Clock extends Component {constructor(props) {super(props);this.state = {date: new Date().toLocaleString()}}componentDidMount() {this.timer = setInterval(() => {// 注意1 不能直接修改state// this.state.date = new Date(); //錯誤// 注意2: setState()是異步的this.setState({date: new Date().toLocaleString()})}, 1000);}componentWillUnmount() {clearInterval(this.timer);}render() {// 修改狀態之后,會重新調用renderreturn (<div><h3>當前時間為:{this.state.date}</h3></div>);} }ReactDOM.render(<Clock />, document.querySelector('#root'));

生命周期

當然react16.x之后,又更新了新的生命周期方法。
如圖,React生命周期主要包括三個階段:初始化階段、運行中階段和銷毀階段,在React不同的生命周期里,會依次觸發不同的鉤子函數,下面我們就來詳細介紹一下React的生命周期函數import React, { Component } from 'react'; import ReactDOM from 'react-dom';class SubCounter extends Component {// 組件將要接收屬性componentWillReceiveProps(newProps){console.log('9.子組件將要接收到新屬性',newProps);}shouldComponentUpdate(newProps,newState){console.log('10.子組件是否需要更新')if(newProps.num % 3 === 0){return true;}else{return false;}}componentWillUpdate() {console.log('11、子組件將要更新');}componentDidUpdate() {console.log('13、子組件更新完成');}componentWillUnmount() {console.log('14、子組件將卸載');}render() {console.log('12.子組件掛載中')return (<div><p>{this.props.num}</p> </div>);} }class Counter extends Component {static defaultyProps = {//1.加載默認屬性name:'小馬哥',age:18}constructor(props) {super(props);//2.記載默認狀態this.state = {num: 0}}componentWillMount() {// 此時可以訪問屬性和狀態,可以進行api調用,但沒辦法做DOM相關操作console.log('3.父組件將要被掛載');}componentDidMount() {// 組件已掛載,可進行狀態更新操作。通常 都在此方法中發送請求console.log('5.組件掛載完成');}shouldComponentUpdate(newProps, newState) {// 組件是否需要更新,返回布爾值,優化點console.log('6.父組件是否被更新');// console.log(newProps, newState);if (newState.num % 2 === 0) {return true;} else {// 此函數 會返回一個boolean值,返回true更新頁面,返回false不更新頁面return false;}}componentWillUpdate(){console.log('7.父組件將要更新');}componentDidUpdate(){console.log('8.父組件更新完成');}handlerClick = () => {// 可能,只是說可能,官網上都是這樣說的.......會導致計數可能不準確,// this.setState({// num: parseInt(this.props.increment) + this.state.num// })// 發現點擊之后,得到的結果為0,這是因為setState()是異步的// console.log(this.state.num);// 要解決這個問題,可以讓 setState() 接收一個函數而不是一個對象。// 這個函數用上一個 state 作為第一個參數,將此次更新被應用時的 props 做為第二個參數this.setState((state, props) => {return {num: state.num + parseInt(props.increment)}}, () => {console.log(this.state.num);})}render() {// 修改狀態之后,會重新調用renderconsole.log('4.render(父組件)渲染了');return (<div><h3>當前數值:{this.state.num}</h3><button onClick={this.handlerClick}>+1</button><h3>我是子組件</h3><SubCounter num = {this.state.num}></SubCounter></div>);} }ReactDOM.render(<Counter increment='1' />, document.querySelector('#root'));

受控組件

受控組件,就是受狀態控制的組件,需要與狀態進行相應的綁定

  • 受控組件必須要有一個 onChange 事件,否則不能使用
  • 受控組件可以賦予默認值(實際上就是設置初始狀態)
  • 官方推薦使用受控組件的寫法

可以使用受控組件實現雙向綁定。
非受控組件,則不是通過與狀態進行綁定來實現的,而是通過操作 DOM 來實現。除非操作 DOM,否則沒有辦法設置默認值。
受控組件實現

  • 設置初始狀態,也就是設置默認值
  • 將輸入框的 value`` 值與相應狀態進行綁定
  • 使用 onChange 事件,對狀態進行修改,從而反映到 value 上
class Input extends Component {constructor() {super();this.state = {val: '' // 這個位置用來設置默認值}}handleChange = (e) => {let val = e.target.valuethis.setState({val});}render() {return (<div>// 讓 value 與狀態進行綁定,通過事件處理修改狀態來達到修改值的效果<input type="text" value={this.state.val} onChange={this.handleChange} />{this.state.val}</div>)} }

非受控組件的實現

  • 通過 ref 標記一個元素,然后可以通過 this.refs.xx 來獲取這個元素
  • 通過 onChange 事件監聽到 value 的變化,獲取到這個數據
  • 然后通過操作 DOM 將數據放到需要的地方
class Input extends Component {constructor() {super();this.state = {val: ''}}handleChange = (e) => {//=> 這里可以通過 e.target.value 獲取let val = this.refs.a.value;this.setState({val});}render() {return (<div><input type="text" onChange={this.handleChange} ref="a" />{this.state.val}</div>)} }實際上,上面實現的只是單向綁定,如果要實現雙向綁定,需要使用兩個 onChange 事件,可以不需要用到狀態

下面來實現雙向綁定:

class Input extends Component {handleChange = (e) => {//=> 這里可以通過 e.target.value 獲取if (e.target === this.refs.a) {this.refs.b.value = e.target.value;} else {this.refs.a.value = e.target.value;}}render() {return (<div onChange={this.handleChange}><input type="text" ref="a" /><input type="text" ref="b" /></div>)} }關于前端學習路線的一些建議,對你一定有用!?www.bilibili.com作者:前端開發小馬哥
鏈接:https://juejin.cn/post/6898512934100533261
來源:掘金

總結

以上是生活随笔為你收集整理的react方法返回html_React全家桶之React基础(推荐新手必看)的全部內容,希望文章能夠幫你解決所遇到的問題。

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