成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

React 可視化開發(fā)工具 Shadow Widget 非正經(jīng)入門(之三:雙源屬性與數(shù)據(jù)驅(qū)動(dòng))

gougoujiang / 842人閱讀

摘要:本篇講解雙源屬性不可變數(shù)據(jù)事件驅(qū)動(dòng)等。可被偵聽,被偵聽后源頭若發(fā)生變化,相應(yīng)的偵聽函數(shù)將自動(dòng)被調(diào)起。本文完本專欄歷史文章介紹一項(xiàng)讓可以與抗衡的技術(shù)可視化開發(fā)工具非正經(jīng)入門之一三宗罪可視化開發(fā)工具非正經(jīng)入門之二分離界面設(shè)計(jì)

本系列博文從 Shadow Widget 作者的視角,解釋該框架的設(shè)計(jì)要點(diǎn)。本篇講解雙源屬性、不可變數(shù)據(jù)、事件驅(qū)動(dòng)等。

1. React 中的隱式雙源
var mainComp = null;

function Welcome(props) {
  return 

Hello, {props.name}

; } class DivText extends React.Component { constructor(props) { super(props); this.state = {name:"Wayne"}; mainComp = this; } render() { return (
); } } ReactDOM.render( , document.getElementById("root") ); setTimeout( function() { mainComp.setState({name:"George"}); },5000);

這個(gè)例子創(chuàng)建的 component 樹如下圖,main 節(jié)點(diǎn)的 state.name 傳遞給 txt 節(jié)點(diǎn)用作 props.nametxt 節(jié)點(diǎn)初始顯示 "Hello, Wayne",過 5 秒后切換為 "Hello, George"。

 
  +-- main      // div
  |   +-- txt   // h1

我們研究一下 5 秒后切換都發(fā)生了什么,mainComp.setState({name:"George"}) 一句更改 main 節(jié)點(diǎn)的 state.name,然后系統(tǒng)觸發(fā)下級 txt 節(jié)點(diǎn)的 props.name 變化,再驅(qū)動(dòng) txt 節(jié)點(diǎn)內(nèi)容刷新。

本處 React 技術(shù)實(shí)現(xiàn)讓初學(xué)者很費(fèi)解,main 節(jié)點(diǎn)的 render 函數(shù)用 JSX 返回 Element,并非每次渲染都用 創(chuàng)建子節(jié)點(diǎn)。

  render() {
    return (
      
); }

而是首次渲染時(shí)創(chuàng)建一次,其后 render() 調(diào)用只對已存在的節(jié)點(diǎn)做更新,由 props.name 變化驅(qū)動(dòng)子節(jié)點(diǎn)內(nèi)容刷新。所以,上面 txt 節(jié)點(diǎn)的 props.name 對節(jié)點(diǎn)自身來說,是不變量,但對父節(jié)點(diǎn)來說,是可變量。由 state.xxx 驅(qū)動(dòng)刷新與 props.xxx 驅(qū)動(dòng)刷新本質(zhì)是一回事,只不過 React 編程模型在表面弄了一點(diǎn)限制。

props.xxx 驅(qū)動(dòng)的刷新是一個(gè)源頭,state.xxx 驅(qū)動(dòng)的刷新是另一個(gè)源頭,合起來是 "雙源驅(qū)動(dòng)"。

2. 改造雙源驅(qū)動(dòng)

由于 React 限定本節(jié)點(diǎn) props.xxx 是只讀的,我們通過改造,讓一個(gè)節(jié)點(diǎn)既接受 props.xxx 驅(qū)動(dòng),也接受 state.xxx 驅(qū)動(dòng)。讓 React 隱式的雙源驅(qū)動(dòng),變成顯式的雙源驅(qū)動(dòng),如下:

var txtComp = null;

class Welcome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {name:props.name};
    this.oldName = props.name;
    txtComp = this;
  }

  render() {
    var name = this.state.name;
    if (this.oldName !== this.props.name)
      name = this.state.name = this.oldName = this.props.name;
    return 

Hello, {name}

; } }

這樣,在 txt 節(jié)點(diǎn),既可用 txtComp.setState({name:"George"}) 驅(qū)動(dòng)刷新,也可由父節(jié)點(diǎn)傳入的 props.name 變化來驅(qū)動(dòng)刷新。我們額外要做的是,在 txt 節(jié)點(diǎn)用 this.oldName 記錄 props.name 舊值,由 this.oldName !== this.props.name 來識別傳入 props.name 是否變化了。

這么改造的意義在于:

自身狀態(tài)變遷與父級驅(qū)動(dòng)變遷,是兩種普遍存在的現(xiàn)象,我們引用正規(guī)的 "雙源驅(qū)動(dòng)" 概念,便于將兩種源頭歸一,如后面敘述,用 this.duals.xxx 表達(dá),歸一后才能構(gòu)造事件發(fā)布與訂閱的機(jī)制。

React 讓 props 屬性只讀的設(shè)計(jì)有點(diǎn)尷尬,有違普遍認(rèn)知。
如前面介紹,它不是不可變,而是限定本級與下級不可修改,這個(gè)規(guī)則對保障單向數(shù)據(jù)傳遞有利。但大眾對 DOM 節(jié)點(diǎn)的認(rèn)知是這樣的,以 為例,type="button" 這個(gè)屬性可以用 props.type 表達(dá),因?yàn)樯嬷芷诶锼辉撚凶兓?,?title="for test" 屬性應(yīng)讓本節(jié)點(diǎn)參與管理,生存期內(nèi)可變。

讓自身節(jié)點(diǎn)管理類似 props.name, props.title 的屬性,大致有兩種方法,其一,采取上面介紹的方法,讓兩個(gè)源頭歸一,再驅(qū)動(dòng)本節(jié)點(diǎn)輸出。其二,按嚴(yán)格的單向數(shù)據(jù)流要求,把代碼寫成下面樣子:

class Welcome extends React.Component {
  constructor(props) {
    super(props);
  }
  
  setName(newName) {
    mainComp.setState({name:newName});
  }
  
  render() {
    return 

Hello, {this.props.name}

; } }

也就是借助父節(jié)點(diǎn)的 setState() 實(shí)現(xiàn)刷新,理論上,這也是單向數(shù)據(jù)流,理解有點(diǎn)別扭,自身節(jié)點(diǎn)的屬性不能直接管理,非要到父節(jié)點(diǎn)跑一圈。

Shadow Widget 雙源驅(qū)動(dòng)的優(yōu)點(diǎn)在于 "讓 DOM 節(jié)點(diǎn)功能回歸本原",讓 props.xxx 服務(wù)于生存周期中不變量,讓 duals.xxx 服務(wù)于可變量,state.xxx 也服務(wù)于可變量,但傾向于用來表達(dá)自身節(jié)點(diǎn)的私有狀態(tài)。

reflux 為實(shí)現(xiàn) React flux 機(jī)制,仿 component 接口設(shè)計(jì)了 store,如果沒有上述 props.xxx 限制,我相信把 component 與 store 合一遠(yuǎn)優(yōu)于現(xiàn)有設(shè)計(jì)?;貧w原本的設(shè)計(jì)好處是潛在的,因?yàn)閮A斜的地基會導(dǎo)致上層建筑更加傾斜。

3. 數(shù)據(jù)偵聽機(jī)制

Shadow Widget 將雙源驅(qū)動(dòng)歸一后,用 duals.attr 存取屬性,而且系統(tǒng)內(nèi)部對讀寫 duals.attr 做了封裝,"讀屬性" 自動(dòng)轉(zhuǎn)從 state.attr 讀值,"寫屬性" 則封裝成事件驅(qū)動(dòng)機(jī)制,等效于調(diào)用 comp.setState({attr:value}),但它所做的事遠(yuǎn)不止這個(gè),還包括:

用戶可以調(diào)用 comp.defineDual(attr,setterFunc) 注冊自定義的 setter 函數(shù),甚至對同一 duals.attr 多次注冊不同 settrer 函數(shù),比如基類定義一個(gè) setter 函數(shù),繼承類中再定義另一個(gè) setter,兩個(gè) setter 會依順被調(diào)用。即 duals.attr 的 setter 也具有一種可繼承的機(jī)制。

duals.attr 可被偵聽,被偵聽后源頭 duals.attr 若發(fā)生變化,相應(yīng)的偵聽函數(shù)將自動(dòng)被調(diào)起。

多個(gè) component 節(jié)點(diǎn)的雙源屬性可以串接,源頭更改其它地方會自動(dòng)更新。

對某節(jié)點(diǎn)的 duals.attr 賦值,會導(dǎo)致多種聯(lián)動(dòng)響應(yīng),如果導(dǎo)致本節(jié)點(diǎn)其它雙源屬性更新,更新將在同一周期立即進(jìn)行,如果導(dǎo)致其它節(jié)點(diǎn)的雙源屬性更新,將在下一周期在其它節(jié)點(diǎn) render() 時(shí)進(jìn)行,如果觸發(fā)偵聽事件,也在下一周期調(diào)用偵聽函數(shù)。Shadow Widget 對 duals.attr 賦值的設(shè)計(jì),已兼顧考慮了本節(jié)點(diǎn)內(nèi)雙源屬性遞歸回調(diào)的效率,也保證了數(shù)據(jù)流傳遞的單向性。

在各節(jié)點(diǎn)注冊 duals.attr 的 setter 函數(shù)、偵聽函數(shù),能自動(dòng)適應(yīng)它的生存周期。比如 B 節(jié)點(diǎn)偵聽 A 節(jié)點(diǎn)的 duals.attr,無論 A 節(jié)點(diǎn),還是 B 節(jié)點(diǎn)先被卸載,偵聽鏈都會自動(dòng)斷開。

偵聽源節(jié)點(diǎn)的雙源屬性,常見代碼有這么兩種寫法:

  sourceComp.listen("attr",targetComp,"attrMethod");
  sourceComp.listen("attr",function(value,oldValue){});

第 1 行寫法的效果是:sourceComp.duals.attr 發(fā)生變化后,自動(dòng)觸發(fā) targetComp["attrMethod"] 的函數(shù)調(diào)用。第 2 行則觸發(fā)由參數(shù)指定的回調(diào)函數(shù)。

4. 數(shù)據(jù)更新的判斷依據(jù)

Shadow Widget 采用 "恒等比較" 的方式判斷兩個(gè)數(shù)值是否更改為,在 comp.duals.attr = valuecomp.setState({attr:value}) 語句中,當(dāng)所賦新值(value)與舊值恒等(即 ===),則視作數(shù)據(jù)未更新,也就不會觸發(fā)相應(yīng)的 setter 調(diào)用或 listen 調(diào)用。

Shadow Widget 已為各構(gòu)件配置 shouldComponentUpdate()componentWillReceiveProps() 缺省處理,除非有特別理由,您不應(yīng)改變?nèi)笔?"以各屬性新舊值是否恒等" 的判斷方式。

至于如何對 Array 或 Object 快速構(gòu)造新數(shù)據(jù),以便被系統(tǒng)判斷為 "非恒等",我們建議用 React addon 提供的 update 接口,Shadow Widget 已缺省內(nèi)置該函數(shù),即 ex.update(),請參考 Shadow Widget 的 API 手冊。

5. 自動(dòng)定義的雙源屬性

雙源屬性一般要調(diào)用 comp.defineDual() 注冊后才使用,但對于 DOM 節(jié)點(diǎn)內(nèi)置屬性是例外,如 title, id, name 等,這些屬性只要節(jié)點(diǎn)在創(chuàng)建時(shí),傳入的 props 用到了,就會被系統(tǒng)自動(dòng)注冊為雙源屬性。

另外,命名為 data-*, aria-*, dual-* 的屬性,也自動(dòng)注冊為雙源屬性。

自動(dòng)注冊雙源屬性的設(shè)計(jì)目的是為了簡化編程,如果遇到不想變成雙源屬性卻自動(dòng)注冊了的情況,不使用 duals.xxx 即可。

(本文完)

本專欄歷史文章:

介紹一項(xiàng)讓 React 可以與 Vue 抗衡的技術(shù)

React 可視化開發(fā)工具 Shadow Widget 非正經(jīng)入門(之一:React 三宗罪)

React 可視化開發(fā)工具 Shadow Widget 非正經(jīng)入門(之二:分離界面設(shè)計(jì))

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/87077.html

相關(guān)文章

  • React 可視開發(fā)工具 Shadow Widget 正經(jīng)入門(之五:指令式界面設(shè)計(jì))

    摘要:本篇解釋中類的控制指令,與指令式界面設(shè)計(jì)相關(guān)。本專欄歷史文章介紹一項(xiàng)讓可以與抗衡的技術(shù)可視化開發(fā)工具非正經(jīng)入門之一三宗罪可視化開發(fā)工具非正經(jīng)入門之二分離界面設(shè)計(jì)可視化開發(fā)工具非正經(jīng)入門之三雙源屬性與數(shù)據(jù)驅(qū)動(dòng)可視化開發(fā)工具非正經(jīng)入門之四 本系列博文從 Shadow Widget 作者的視角,解釋該框架的設(shè)計(jì)要點(diǎn)。本篇解釋 Shadow Widget 中類 Vue 的控制指令,與指令式界面...

    pinecone 評論0 收藏0
  • React 可視開發(fā)工具 Shadow Widget 正經(jīng)入門(之一:React 三宗罪)

    摘要:前言非正經(jīng)入門是相對正經(jīng)入門而言的。不過不要緊,正式學(xué)習(xí)仍需回到正經(jīng)入門的方式。快速入門建議先學(xué)會用拼文寫文檔注冊一個(gè)賬號,把庫到自己名下,然后用這個(gè)庫寫自己的博客,參見這份介紹。會用拼文寫文章,相當(dāng)于開發(fā)已入門三分之一了。 本系列博文從 Shadow Widget 作者的視角,解釋該框架的設(shè)計(jì)要點(diǎn),既作為用戶手冊的補(bǔ)充,也從更本質(zhì)角度幫助大家理解 Shadow Widget 為什么這...

    dongxiawu 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<