真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

React中怎么實(shí)現(xiàn)受控組件與非受控組件

本篇文章給大家分享的是有關(guān)React中怎么實(shí)現(xiàn)受控組件與非受控組件,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

創(chuàng)新互聯(lián)長(zhǎng)期為上1000家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為恒山企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、做網(wǎng)站,恒山網(wǎng)站改版等技術(shù)服務(wù)。擁有十載豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。

受控組件與非受控組件是React處理表單的入口。從React的思路來(lái)講,作者肯定讓數(shù)據(jù)控制一切,或者簡(jiǎn)單的理解為,頁(yè)面的生成與更新得忠實(shí)地執(zhí)行JSX的指令。

但是表單元素有其特殊之處,用戶可以通過(guò)鍵盤輸入與鼠標(biāo)選擇,改變界面的顯示。界面的改變也意味著有一些數(shù)據(jù)被改動(dòng),比較明顯的是input的 value ,textarea的 innerHTML ,radio/checkbox的 checked ,不太明顯的是option的 selected 與 selectedIndex ,這兩個(gè)是被動(dòng)修改的。

 

 當(dāng)input.value是由組件的state.value拍出來(lái)的,當(dāng)用戶進(jìn)行輸入修改后,然后JSX再次重刷視圖,這時(shí)input.value是采取用戶的新值還是state的新值?基于這個(gè)分歧,React給出一個(gè)折衷的方案,兩者都支持,于是就產(chǎn)生了今天的主題了。

React認(rèn)為value/checked不能單獨(dú)存在,需要與onInput/onChange/disabed/readOnly等控制value/checked的屬性或事件一起使用。 它們共同構(gòu)成 受控組件 ,受控是受JSX的控制。如果用戶沒有寫這些額外的屬性與事件,那么框架內(nèi)部會(huì)給它添加一些事件,如onClick, onInput, onChange,阻止你進(jìn)行輸入或選擇,讓你無(wú)法修改它的值。在框架內(nèi)部,有一個(gè)頑固的變量,我稱之為 persistValue,它一直保持JSX上次賦給它的值,只能讓內(nèi)部事件修改它。

因此我們可以斷言,受控組件是可通過(guò) 事件 完成的對(duì)value的控制。

在受控組件中,persistValue總能被刷新。

我們?cè)倏捶鞘芸亟M件,既然value/checked已經(jīng)被占用了,React啟用了HTML中另一組被忽略的屬性defaultValue/defaultChecked。一般認(rèn)為它們是與value/checked相通的,即,value不存在的情況下,defaultValue的值就當(dāng)作是value。

上面我們已經(jīng)說(shuō)過(guò),表單元素的顯示情況是由內(nèi)部的 persistValue 控制的,因此defaultXXX也會(huì)同步persistValue,然后再由persistValue同步DOM。但非受控組件的出發(fā)點(diǎn)是忠實(shí)于用戶操作,如果用戶在代碼中

input.value = "xxxx"

以后

就再不生效,一直是xxxx。

它怎么做到這一點(diǎn),怎么辨識(shí)這個(gè)修改是來(lái)自框架內(nèi)部或外部呢?我翻看了一下React的源碼,原來(lái)它有一個(gè)叫valueTracker的東西跟蹤用戶的輸入

var tracker = {
  getValue: function () {
   return currentValue;
  },
  setValue: function (value) {
   currentValue = '' + value;
  },
  stopTracking: function () {
   detachTracker(node);
   delete node[valueField];
  }
 };
 return tracker;
}

這個(gè)東西又是通過(guò)Object.defineProperty打進(jìn)元素的value/checked的內(nèi)部,因此就知曉用戶對(duì)它的取值賦值操作。

但value/checked還是兩個(gè)很核心的屬性,涉及到太多內(nèi)部機(jī)制(比如說(shuō)value與oninput, onchange, 輸入法事件oncompositionstart,

compositionchange, oncompositionend, onpaste, oncut),為了平緩地修改value/checked,

還要用到 Object.getOwnPropertyDescriptor 。如果我要兼容IE8,沒有這么高級(jí)的玩藝兒。我采取另一種更安全的方式,

只用Object.defineProperty修改 defaultValue/defaultChecked 。

首先我為元素添加一個(gè) _uncontrolled 的屬性,用來(lái)表示我已經(jīng)劫持過(guò)defaultXXX。 然后描述對(duì)象 ( Object.defineProperty的第三個(gè)參數(shù) )的set方法里面再添加一個(gè)開關(guān), _observing 。在框架內(nèi)部更新視圖,此值為false,更新完,它置為true。

這樣就知曉 input.defaultValue = “xxx”時(shí),這是由用戶還是框架修改的。

if (!dom._uncontrolled) {
  dom._uncontrolled = true;
  inputMonitor.observe(dom, name); //重寫defaultXXX的setter/getter
}
dom._observing = false;//此時(shí)是框架在修改視圖,因此需要關(guān)閉開關(guān)
dom[name] = val;
dom._observing = true;//打開開關(guān),來(lái)監(jiān)聽用戶的修改行為

inputMonitor的實(shí)現(xiàn)如下

export var inputMonitor = {};
var rcheck = /checked|radio/;
var describe = {
  set: function(value) {
    var controllProp = rcheck.test(this.type) ? "checked" : "value";
    if (this.type === "textarea") {
      this.innerHTML = value;
    }
    if (!this._observing) {
      if (!this._setValue) {
        //defaultXXX只會(huì)同步一次_persistValue
        var parsedValue = (this[controllProp] = value);
        this._persistValue = Array.isArray(value) ? value : parsedValue;
        this._setValue = true;
      }
    } else {
      //如果用戶私下改變defaultValue,那么_setValue會(huì)被抺掉
      this._setValue = value == null ? false : true;
    }
    this._defaultValue = value;
  },
  get: function() {
    return this._defaultValue;
  },
  configurable: true
};
 
inputMonitor.observe = function(dom, name) {
  try {
    if ("_persistValue" in dom) {
      dom._setValue = true;
    }
    Object.defineProperty(dom, name, describe);
  } catch (e) {}
};

又不小心貼了這么燒腦的代碼,這是碼農(nóng)的壞毛病。不過(guò),到這步,大家都明白,無(wú)論是官方react還是anu/qreact都是通過(guò)Object.defineProperty來(lái)控制用戶的輸入的。

于是我們可以理解以下的代碼的行為了

  var a = ReactDOM.render(, container);
  ReactDOM.render(, container);
  ReactDOM.render(, container);
  expect(a.defaultValue).toBe("noise");
  expect(a.value).toBe("foo");
  expect(a.textContent).toBe("noise");
  expect(a.innerHTML).toBe("noise");

由于用戶一直沒有手動(dòng)修改 defaultValue, dom._setValue 一直為 false/undefined ,因此 _persistValue 一直能修改。

另一個(gè)例子:

var renderTextarea = function(component, container) {
  if (!container) {
    container = document.createElement("div");
  }
  const node = ReactDOM.render(component, container);
  node.defaultValue = node.innerHTML.replace(/^\n/, "");
  return node;
};
 
const container = document.createElement("div");
//注意這個(gè)方法,用戶在renderTextarea中手動(dòng)改變了defaultValue,_setValue就變成true
const node = renderTextarea(, container);
 
expect(node.value).toBe("giraffe");
 
// _setValue后,gorilla就不能同步到_persistValue,因此還是giraffe
renderTextarea(, container);
// expect(node.value).toEqual("giraffe");
 
node.value = "cat";
// 這個(gè)又是什么回事了呢,因此非監(jiān)控屬性是在diffProps中批量處理的,在監(jiān)控屬性,則是在更后的方法中處理
// 檢測(cè)到node.value !== _persistValue,于是重寫 _persistValue = node.value,于是輸出cat
renderTextarea(, container);
expect(node.value).toEqual("cat");

純文本類:text, textarea, JSX的值,總是往字符串轉(zhuǎn)換

type=”number”的控制,值總是為數(shù)字,不填或?yàn)椤啊眲t轉(zhuǎn)換為“0”

radio有聯(lián)動(dòng)效果,同一父節(jié)點(diǎn)下的相同name的radio控制只能選擇一個(gè)。

select的value/defaultValue支持?jǐn)?shù)組,不做轉(zhuǎn)換,但用戶對(duì)底下的option元素做增刪操作,selected會(huì)跟著變動(dòng)。

此外select還有模糊匹配與精確匹配之分。

//精確匹配
var dom = ReactDOM.render(
  
    aaa
    xxx
    bbb
    ccc
  ,
  container
);
expect(dom.options[2].selected).toBe(true);//選中第三個(gè)
//模糊匹配
var dom = ReactDOM.render(
  
    aaa
    xxx
    ccc
  ,
  container
);
expect(dom.options[2].selected).toBe(true);//選中第二個(gè)

以上就是React中怎么實(shí)現(xiàn)受控組件與非受控組件,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


新聞名稱:React中怎么實(shí)現(xiàn)受控組件與非受控組件
轉(zhuǎn)載來(lái)源:http://weahome.cn/article/ijocgh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部