摘要:小明小明兒子,可以看到組件顯示了父組件的。小明受控組件和非受控組件受控組件和非受控組件這些都是指的表單組件,當(dāng)一個(gè)表單的值是通過(guò)改變的而不是通過(guò)是受控組件,否則就是非受控組件。
react眾所周知的前端3大主流框架之一,由于出色的性能,完善的周邊設(shè)施風(fēng)頭一時(shí)無(wú)兩。本文就帶大家一起掌握react。
jsx語(yǔ)法前端MVVM主流框架都有一套自己的模板處理方法,react則使用它獨(dú)特的jsx語(yǔ)法。在組件中插入html類似的語(yǔ)法,簡(jiǎn)化創(chuàng)建view的流程。
下面讓我們來(lái)認(rèn)識(shí)一下構(gòu)建的兩種元素
原生元素ReactDOM.render((), document.getElementById("root"))標(biāo)題
通過(guò)簡(jiǎn)單的語(yǔ)法頁(yè)面就會(huì)被插入一個(gè)div+一個(gè)h1標(biāo)簽。原生的html元素可以被直接使用。以上的語(yǔ)法并不是js支持的語(yǔ)法,需要被轉(zhuǎn)換之后才能運(yùn)行。
自定義元素react強(qiáng)大之處就在于可以組件的自定義,實(shí)現(xiàn)組件的復(fù)用。如果我們創(chuàng)建了一個(gè)組件。我們也可以通過(guò)jsx語(yǔ)法調(diào)用。
import * as React from "react" class Page extends React.Component { render() { return (home111 © ? ua9) } } ReactDOM.render((), document.getElementById("root"))
我們定義了一個(gè)Page組件,可以在jsx里面像調(diào)用html一樣直接調(diào)用。
插入動(dòng)態(tài)數(shù)據(jù)let name = "hi" ReactDOM.render(({name}), document.getElementById("root"))
使用{}就可以插入數(shù)據(jù),但是{}中間的必須是js表達(dá)式,不能是語(yǔ)句。如果表達(dá)式的執(zhí)行結(jié)果是一個(gè)數(shù)組,則會(huì)自動(dòng)join。
注釋jsx語(yǔ)法和html語(yǔ)法一樣,也是可以插入注釋,只不過(guò)寫的時(shí)候有一些區(qū)別
子組件注釋let name = "hi" ReactDOM.render(({/* 注釋 */} {name}), document.getElementById("root"))
在子組件中插入注釋,需要使用{}包裹起來(lái),在/ /之間插入注釋文字。
屬性注釋let name = "hi" ReactDOM.render(({name}), document.getElementById("root"))
在標(biāo)簽中間,可以插入一個(gè)多行注釋,類似上面的代碼。
屬性props可以向使用html的attr一樣使用屬性,就像下面img的src一樣
let name = "hi" ReactDOM.render((), document.getElementById("root"))
如果需要傳遞動(dòng)態(tài)屬性,使用{},多個(gè)屬性,使用展開(kāi)運(yùn)算符
let props = { src: "1.png", alt: "1圖片" } ReactDOM.render((), document.getElementById("root"))
兩個(gè)轉(zhuǎn)換,class-->className for-->htmlFor
因?yàn)閏lass和for是javascript關(guān)鍵字,所以這里需要用轉(zhuǎn)換之后名稱
ReactDOM.render((), document.getElementById("root"))
布爾屬性
如果一個(gè)屬性的值是布爾值,當(dāng)這個(gè)值是true的時(shí)候則可以省略=后面的值,只保留key。
ReactDOM.render((), document.getElementById("root"))
原生元素的自定義屬性
react對(duì)元素屬性做了校驗(yàn),如果在原生屬性上使用此元素不支持的屬性,則不能編譯成功。必須使用data-前綴
ReactDOM.render((插入html), document.getElementById("root"))
如果動(dòng)態(tài)的插入html元素,react出于安全性考慮會(huì)自動(dòng)幫我們轉(zhuǎn)義。所以一定要?jiǎng)討B(tài)的插入元素的話,使用dangerouslySetInnerHTML
ReactDOM.render((React組件創(chuàng)建 React.createClass), document.getElementById("root"))test"}}>
這是舊版本的api,使用React.createClass創(chuàng)建組件,配套的一些api,有g(shù)etDefaultProps, getinitialstate。官方已經(jīng)不建議使用了,使用下面新的api替代。
ES6 classesimport * as React from "react" class Page extends React.Component { render() { return (home) } }
這是一個(gè)實(shí)現(xiàn)了render方法的class。也是一個(gè)基本的react組件。
無(wú)狀態(tài)函數(shù)function Button(props, context) { return ( ); }
純函數(shù),不存在state,只接受props和state。純函數(shù)有優(yōu)點(diǎn),優(yōu)點(diǎn)就是易于測(cè)試,無(wú)副作用。
React數(shù)據(jù)流 statestate是組件的內(nèi)部狀態(tài),需要在視圖里面用到的狀態(tài),才需要放到state里面去。如下,我們?cè)陬惿蟿?chuàng)建一個(gè)state屬性,在視圖里面通過(guò)使用this.state.name去引用。而這里的state定義則代替的是getinitialstate方法。
import * as React from "react" class Page extends React.Component { state = { name: "小明" } render() { return ({this}) } }
如何更新state呢,直接更改state其實(shí)可以可以的,不過(guò)這樣子無(wú)法觸發(fā)組件視圖的更新機(jī)制。所以使用setState()api。值得注意的是setState是異步的,原因是react內(nèi)部需要對(duì)setState做優(yōu)化,不是state變了立刻去更新視圖,而是攔截一部分state的改變,等到合適的時(shí)機(jī)再去更新視圖。
import * as React from "react" class Page extends React.Component { state = { name: "小明" } render() { setTimeout(() => this.setState({name: "小明兒子"}), 5000) return ({this.state.name}) } }
真實(shí)開(kāi)發(fā)中絕不要在render函數(shù)里面去更改state,以上只是為了演示props
props是組件之間傳遞數(shù)據(jù)的最主要api, react推崇的是自頂向下的數(shù)據(jù)流向,也就是組件的數(shù)據(jù)要從父組件傳給子組件。如果子組件需要向父組件傳遞數(shù)據(jù),則需要使用回調(diào)函數(shù)的方式。
import * as React from "react" class Child extends React.Component { render() { return ({this.props.parentName}) } } class Parent extends React.Component { state = { name: "小明" } render() { setTimeout(() => this.setState({name: "小明兒子"}), 5000) return () } }
可以看到Child組件顯示了父組件的name。當(dāng)父組件狀態(tài)更新了,子組件同步更新。那如何在子組件中更改父組件狀態(tài)呢?答案是回調(diào)函數(shù)。
import * as React from "react" class Child extends React.Component { update() { this.props.onChange("小明名字改了") } render() { return ({this.props.parentName}) } } class Parent extends React.Component { state = { name: "小明" } changeName(name) { this.setState({ name }) } render() { setTimeout(() => this.setState({name: "小明兒子"}), 5000) return () } }
注意哈:props是不可以更改的,這既不符合react單向數(shù)據(jù)流思想,也為維護(hù)帶來(lái)災(zāi)難。
事件react里面的用戶事件都是合成事件,被React封裝過(guò)。內(nèi)部使用的還是事件的委托機(jī)制。
常用的事件有點(diǎn)擊事件onClick,input的onChange事件等,官網(wǎng)都可以查到。
就像上文一樣,我們綁定事件的方式很奇怪,使用了bind來(lái)顯示綁定this的指向。因?yàn)閭鬟f到組件內(nèi)部的只是一個(gè)函數(shù),而脫離了當(dāng)前對(duì)象的函數(shù)的this指向是不能指到當(dāng)前組件的,需要顯示指定。
通過(guò)bind 構(gòu)造器內(nèi)部指定import * as React from "react" class Child extends React.Component { constructor(props) { super(props) this.update = this.update.bind(this) } update() { this.props.onChange("小明名字改了") } render() { return (箭頭函數(shù){this.props.parentName}) } }
import * as React from "react" class Child extends React.Component { update => e = { this.props.onChange("小明名字改了") } render() { return (裝飾器{this.props.parentName}) } }
import * as React from "react" class Child extends React.Component { constructor(props) { super(props) } @autoBind update() { this.props.onChange("小明名字改了") } render() { return ({this.props.parentName}) } }
裝飾器是es7語(yǔ)法,如果需要使用需要安裝對(duì)應(yīng)的babel:present版本。而typescript則原生支持。
autoBind原理大概就是劫持get方法,get時(shí)改變this指向如何獲得evnt原生事件
通過(guò)e.nativeEvent獲取原生事件對(duì)象
import * as React from "react" class Child extends React.Component { constructor(props) { super(props) this.update = this.update.bind(this) } update(e) { console.log(e.nativeEvent) } render() { return (解決冒泡和取消默認(rèn)事件) } }
e.preventDefault() //取消默認(rèn)行為
e.stopPropagation() //取消冒泡
這個(gè)和瀏覽器原生事件處理方案是一致的。問(wèn)題是我們只可以調(diào)合成事件的e的方法,不可以通過(guò)e.nativeEvent方法做這些操作,原因是上文講過(guò)的委托。
ReactDom ref特殊的props,ref組件對(duì)象的引用,現(xiàn)在官方也不建議直接給ref賦值,需要通過(guò)函數(shù)來(lái)賦值。
ReactDOM.render((render), document.getElementById("root"))this.c = ref} any-ss="text"/>
頂層api,只有在根組件時(shí)候才需要使用。第一個(gè)參數(shù)是Component,第二個(gè)參數(shù)是dom節(jié)點(diǎn)
findDOMNode通過(guò)傳入component實(shí)例獲取此component根dom節(jié)點(diǎn),在這里可以去dom節(jié)點(diǎn)進(jìn)行操作了,雖然極其不建議這么做,但是你確實(shí)可以做。
unmountComponentAtNode卸載此組件,并銷毀組件state和事件
接收組件的引用,也就是ref。僅僅是取消掛載,組件還在,如果需要徹底清除的話,需要手動(dòng)刪掉此dom。
表單 onchange配合value與vue框架不同的是,react如果要實(shí)現(xiàn)表單元素變化,狀態(tài)同步更新,必須要自己去監(jiān)聽(tīng)表單事件。
import * as React from "react" class Child extends React.Component { state = { name: "小明" } constructor(props) { super(props) this.update = this.update.bind(this) } update(e) { this.setState({ name: e.target.value }) } render() { return (受控組件和非受控組件) } }
受控組件和非受控組件這些都是指的表單組件,當(dāng)一個(gè)表單的值是通過(guò)value改變的而不是通過(guò)defaultValue是受控組件,否則就是非受控組件。
下面組件中的input就是受控組件
import * as React from "react" class Child extends React.Component { state = { name: "小明" } constructor(props) { super(props) this.update = this.update.bind(this) } update(e) { this.setState({ name: e.target.value }) } render() { return () } }
下面組件中的input是非受控組件
import * as React from "react" class Child extends React.Component { state = { name: "小明" } constructor(props) { super(props) this.update = this.update.bind(this) } update(e) { this.setState({ name: e.target.value }) } render() { return (組件之間通訊 父子之間通訊) } }
父子之間通訊又分為父->子,子->父。
因?yàn)閞eact單向數(shù)據(jù)流向的緣故,父->子通信的話直接通過(guò)props。父組件數(shù)據(jù)變動(dòng),直接傳遞給子組件。
子->父組件之間就要通過(guò)回調(diào)函數(shù)來(lái)通信了,父組件傳遞一個(gè)回調(diào)函數(shù)給子組件,子組件通過(guò)調(diào)用此函數(shù)的方式通知父組件通信。
跨級(jí)組件通信react為了實(shí)現(xiàn)祖先組件和后輩組件之間的通信問(wèn)題,引入了contextApi。
class Button extends React.Component { render() { return ( ); } } Button.contextTypes = { color: React.PropTypes.string }; class Message extends React.Component { render() { return ({this.props.text}); } } class MessageList extends React.Component { getChildContext() { return {color: "purple"}; } render() { const children = this.props.messages.map((message) =>); return {children}; } } MessageList.childContextTypes = { color: React.PropTypes.string };
MessageList中的color會(huì)自動(dòng)更新到兒孫組件里面去,實(shí)現(xiàn)跨級(jí)啊通信。如果需要反過(guò)來(lái)通信,則需要借助其他工具,比如事件系統(tǒng)(Pub/Sub)。
沒(méi)有嵌套關(guān)系組件之間通信組件之間通信最主流的兩種方式脫胎于觀察這模式和中介者模式這兩種。
跨級(jí)之間通信現(xiàn)在最主流的方式就是觀察這模式的實(shí)現(xiàn)Pub/Sub,react社區(qū)中的redux也是使用這種方式實(shí)現(xiàn)的。
vue2.X版本也去掉了跨組件通信的功能。那如何在2.x中做跨組件通信呢?如果不借助外力的話,是不是可以使用$parent和$childen的遞歸調(diào)用實(shí)現(xiàn)全局組件通信呢?比如我想廣播一個(gè)事件,我就查找到所有的子組件,挨個(gè)觸發(fā)$emit(xx),上報(bào)一個(gè)事件也是同理,只不過(guò)需要查找所有的$parent。結(jié)合起來(lái)就可以實(shí)現(xiàn)組件之間的通信,只不過(guò)這種查找效率比較低,需要慎用和優(yōu)化
創(chuàng)建了一個(gè)程序員交流微信群,大家進(jìn)群交流IT技術(shù)
如果已過(guò)期,可以添加博主微信號(hào)15706211347,拉你進(jìn)群
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97409.html
摘要:前言上一次我們對(duì)的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來(lái)聊聊。 showImg(https://segmentfault.com/img/remote/1460000020077803?w=1280&h=853); 前言 上一次我們對(duì)Paging的應(yīng)用進(jìn)行了一次全面的分析,這一次我們來(lái)聊聊WorkManager。 如果你對(duì)Paging還未了解,推薦閱讀這篇文章: Paging在Recy...
摘要:采用完全獨(dú)立于任何程序語(yǔ)言的文本格式,使成為理想的數(shù)據(jù)交換語(yǔ)言為什么需要提到,我們就應(yīng)該和來(lái)進(jìn)行對(duì)比。也是一種存儲(chǔ)和交換文本信息的手段。那么好在哪里呢比更小更快,更易解析。使用的時(shí)候,也支持將轉(zhuǎn)成但是,我們不一定使用框架來(lái)做開(kāi)發(fā)呀。 什么是JSON JSON:JavaScript Object Notation 【JavaScript 對(duì)象表示法】 JSON 是存儲(chǔ)和交換文本信息的語(yǔ)法...
摘要:目錄前言架構(gòu)安裝第一個(gè)爬蟲(chóng)爬取有道翻譯創(chuàng)建項(xiàng)目創(chuàng)建創(chuàng)建解析運(yùn)行爬蟲(chóng)爬取單詞釋義下載單詞語(yǔ)音文件前言學(xué)習(xí)有一段時(shí)間了,當(dāng)時(shí)想要獲取一下百度漢字的解析,又不想一個(gè)個(gè)漢字去搜,復(fù)制粘貼太費(fèi)勁,考慮到爬蟲(chóng)的便利性,這篇文章是介紹一個(gè)爬蟲(chóng)框架, 目錄 前言 架構(gòu) 安裝 第一個(gè)爬蟲(chóng):爬取有道翻譯 創(chuàng)建項(xiàng)目 創(chuàng)建Item 創(chuàng)建Spider 解析 運(yùn)行爬蟲(chóng)-爬取單詞釋義 下載單詞語(yǔ)音文件 ...
摘要:如果我們想要多次輸出類中的成員信息,就需要多次書(shū)寫方法每用一次就得寫而調(diào)用就簡(jiǎn)單多了補(bǔ)充兩者等價(jià)輸出結(jié)果。注一般選擇重寫方法,比較對(duì)象的成員變量值是否相同,不過(guò)一般重寫都是自動(dòng)生成。 第三階段 JAVA常見(jiàn)對(duì)象的學(xué)習(xí) 第一章 常見(jiàn)對(duì)象——Object類 引言: 在講解Object類之前,我們不得不簡(jiǎn)單的提一下什么是API,先貼一組百度百科的解釋: API(Application Pro...
摘要:相信很多人在格式化字符串的時(shí)候都用的語(yǔ)法,提出一種更先進(jìn)的格式化方法并成為的標(biāo)準(zhǔn)用來(lái)替換舊的格式化語(yǔ)法,從開(kāi)始已經(jīng)實(shí)現(xiàn)了這一方法其它解釋器未考證。 showImg(https://segmentfault.com/img/remote/1460000018650325); 相信很多人在格式化字符串的時(shí)候都用%s % v的語(yǔ)法,PEP 3101 提出一種更先進(jìn)的格式化方法 str.for...
閱讀 2326·2021-09-22 15:27
閱讀 3178·2021-09-03 10:32
閱讀 3506·2021-09-01 11:38
閱讀 2503·2019-08-30 15:56
閱讀 2220·2019-08-30 13:01
閱讀 1543·2019-08-29 12:13
閱讀 1425·2019-08-26 13:33
閱讀 899·2019-08-26 13:30