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

資訊專欄INFORMATION COLUMN

React 模式(中文版)

hzx / 1428人閱讀

摘要:渲染屬性這里有個(gè)組件,使用了一個(gè)渲染回調(diào)函數(shù)。這個(gè)狀態(tài)被提升到了容器中,通過添加回調(diào)函數(shù),回調(diào)中可以更新本地狀態(tài)。這個(gè)是正常的受控的輸入不允許變更,這使得這個(gè)模式成為可能。

中文版:https://reactpatterns.cn/
原版:https://reactpatterns.com

函數(shù)組件 (Function component)

函數(shù)組件 是最簡(jiǎn)單的一種聲明可復(fù)用組件的方法

他們就是一些簡(jiǎn)單的函數(shù)。

function Greeting() {
  return 
Hi there!
; }

從第一個(gè)形參中獲取屬性集 (props)

function Greeting(props) {
  return 
Hi {props.name}!
; }

按自己的需要可以在函數(shù)組件中定義任意變量

最后一定要返回你的 React 組件。

function Greeting(props) {
  let style = {
    fontWeight: "bold",
    color: context.color
  };

  return 
Hi {props.name}!
; }

使用 defaultProps 為任意必有屬性設(shè)置默認(rèn)值

function Greeting(props) {
  return 
Hi {props.name}!
; } Greeting.defaultProps = { name: "Guest" };
屬性解構(gòu) (Destructuring props)

解構(gòu)賦值 是一種 JavaScript 特性。

出自 ES2015 版的 JavaScript 新規(guī)范。

所以看起來可能并不常見。

好比字面量賦值的反轉(zhuǎn)形式。

let person = { name: "chantastic" };
let { name } = person;

同樣適用于數(shù)組。

let things = ["one", "two"];
let [first, second] = things;

解構(gòu)賦值被用在很多 函數(shù)組件 中。

下面聲明的這些組件是相同的。

function Greeting(props) {
  return 
Hi {props.name}!
; } function Greeting({ name }) { return
Hi {name}!
; }

有一種語(yǔ)法可以在對(duì)象中收集剩余屬性。

叫做 剩余參數(shù),看起來就像這樣。

function Greeting({ name, ...restProps }) {
  return 
Hi {name}!
; }

那三個(gè)點(diǎn) (...) 會(huì)把所有的剩余屬性分配給 restProps 對(duì)象

然而,你能使用 restProps 做些什么呢?

繼續(xù)往下看...

JSX 中的屬性展開 (JSX spread attributes)

屬性展開是 JSX 中的一個(gè)的特性。

它是一種語(yǔ)法,專門用來把對(duì)象上的屬性轉(zhuǎn)換成 JSX 中的屬性

參考上面的 屬性解構(gòu)),
我們可以 擴(kuò)散 restProps 對(duì)象的所有屬性到 div 元素上

function Greeting({ name, ...restProps }) {
  return 
Hi {name}!
; }

這讓 Gretting 組件變得非常靈活。

我們可以通過傳給 Gretting 組件 DOM 屬性并確定這些屬性一定會(huì)被傳到 div

避免傳遞非 DOM 屬性到組件上。
解構(gòu)賦值是如此的受歡迎,是因?yàn)樗梢苑蛛x 組件特定的屬性DOM/平臺(tái)特定屬性

function Greeting({ name, ...platformProps }) {
  return 
Hi {name}!
; }
合并解構(gòu)屬性和其它值 (Merge destructured props with other values)

組件就是一種抽象。

好的抽象是可以擴(kuò)展的。

比如說下面這個(gè)組件使用 class 屬性來給按鈕添加樣式。

function MyButton(props) {
  return 

一般情況下這樣做就夠了,除非我們需要擴(kuò)展其它的樣式類

Delete...

在這個(gè)例子中把 btn 替換成 delete-btn

JSX 中的屬性展開) 對(duì)先后順序是敏感的

擴(kuò)散屬性中的 className 會(huì)覆蓋組件上的 className。

我們可以改變它兩的順序,但是目前來說 className 只有 btn

function MyButton(props) {
  return 

我們需要使用解構(gòu)賦值來合并入?yún)?props 中的 className 和基礎(chǔ)的(組件中的) className。
可以通過把所有的值放在一個(gè)數(shù)組里面,然后使用一個(gè)空格連接它們。

function MyButton({ className, ...props }) {
  let classNames = ["btn", className].join(" ");

  return 

為了保證 undefined 不被顯示在 className 上,可以使用 默認(rèn)值。

function MyButton({ className = "", ...props }) {
  let classNames = ["btn", className].join(" ");

  return 
條件渲染 (Conditional rendering)

不可以在一個(gè)組件聲明中使用 if/else 語(yǔ)句
You can"t use if/else statements inside a component declarations.
所以可以使用 條件(三元)運(yùn)算符 和 短路計(jì)算。

如果
{
  condition && Rendered when `truthy`;
}
除非
{
  condition || Rendered when `falsy`;
}
如果-否則
{
  condition ? (
    Rendered when `truthy`
  ) : (
    Rendered when `falsy`
  );
}
子元素類型 (Children types)

很多類型都可以做為 React 的子元素。

多數(shù)情況下會(huì)是 數(shù)組 或者 字符串

字符串 String
Hello World!
數(shù)組 Array
{["Hello ", World, "!"]}
數(shù)組做為子元素 (Array as children)

將數(shù)組做為子元素是很常見的。

列表是如何在 React 中被繪制的。

我們使用 map() 方法創(chuàng)建一個(gè)新的 React 元素?cái)?shù)組

    {["first", "second"].map(item => (
  • {item}
  • ))}

這和使用字面量數(shù)組是一樣的。

    {[
  • first
  • ,
  • second
  • ]}

這個(gè)模式可以聯(lián)合解構(gòu)、JSX 屬性擴(kuò)散以及其它組件一起使用,看起來簡(jiǎn)潔無比

    {arrayOfMessageObjects.map(({ id, ...message }) => ( ))}
函數(shù)做為子元素 (Function as children)

React 組件不支持函數(shù)類型的子元素。

然而 渲染屬性 是一種可以創(chuàng)建組件并以函數(shù)作為子元素的模式。

渲染屬性 (Render prop)

這里有個(gè)組件,使用了一個(gè)渲染回調(diào)函數(shù) children。

這樣寫并沒有什么用,但是可以做為入門的簡(jiǎn)單例子。

const Width = ({ children }) => children(500);

組件把 children 做為函數(shù)調(diào)用,同時(shí)還可以傳一些參數(shù)。上面這個(gè) 500 就是實(shí)參。

為了使用這個(gè)組件,我們可以在調(diào)用組件的時(shí)候傳入一個(gè)子元素,這個(gè)子元素就是一個(gè)函數(shù)。

{width => 
window is {width}
}

我們可以得到下面的輸出。

window is 500

有了這個(gè)組件,我們就可以用它來做渲染策略。


  {width => (width > 600 ? 
min-width requirement met!
: null)}

如果有更復(fù)雜的條件判斷,我們可以使用這個(gè)組件來封裝另外一個(gè)新組件來利用原來的邏輯。

const MinWidth = ({ width: minWidth, children }) => (
  {width => (width > minWidth ? children : null)}
);

顯然,一個(gè)靜態(tài)的 Width 組件并沒有什么用處,但是給它綁定一些瀏覽器事件就不一樣了。下面有個(gè)實(shí)現(xiàn)的例子。

class WindowWidth extends React.Component {
  constructor() {
    super();
    this.state = { width: 0 };
  }

  componentDidMount() {
    this.setState(
      { width: window.innerWidth },
      window.addEventListener("resize", ({ target }) =>
        this.setState({ width: target.innerWidth })
      )
    );
  }

  render() {
    return this.props.children(this.state.width);
  }
}

許多開發(fā)人員都喜歡 高階組件 來實(shí)現(xiàn)這種功能。但這只是個(gè)人喜好問題。

子組件的傳遞 (Children pass-through)

你可能會(huì)創(chuàng)建一個(gè)組件,這個(gè)組件會(huì)使用 context 并且渲染它的子元素。

class SomeContextProvider extends React.Component {
  getChildContext() {
    return { some: "context" };
  }

  render() {
    // 如果能直接返回 `children` 就完美了
  }
}

你將面臨一個(gè)選擇。把 children 包在一個(gè) div 中并返回,或者直接返回 children。第一種情況需要要你添加額外的標(biāo)記(這可能會(huì)影響到你的樣式)。第二種將產(chǎn)生一個(gè)沒什么用處的錯(cuò)誤。

// option 1: extra div
return 
{children}
; // option 2: unhelpful errors return children;

最好把 children 做為一種不透明的數(shù)據(jù)類型對(duì)待。React 提供了 React.Children 方法來處理 children。

return React.Children.only(this.props.children);
代理組件 (Proxy component)

(我并不確定這個(gè)名字的準(zhǔn)確叫法 譯:代理、中介、裝飾?)

按鈕在 web 應(yīng)用中隨處可見。并且所有的按鈕都需要一個(gè) type="button" 的屬性。

重復(fù)的寫這些屬性很容易出錯(cuò)。我們可以寫一個(gè)高層組件來代理 props 到底層組件。

const Button = props =>
  

我們可以使用 Button 組件代替 button 元素,并確保 type 屬性始終是 button。


// 
樣式組件 (Style component)

這也是一種 代理組件,用來處理樣式。

假如我們有一個(gè)按鈕,它使用了「primary」做為樣式類。

我們使用一些單一功能組件來生成上面的結(jié)構(gòu)。

import classnames from "classnames";

const PrimaryBtn = props => ;

const Btn = ({ className, primary, ...props }) => (
  

可以可視化的展示成下面的樣子。

PrimaryBtn()
  ? Btn({primary: true})
    ? Button({className: "btn btn-primary"}, type: "button"})
      ? ""

使用這些組件,下面的這幾種方式會(huì)得到一致的結(jié)果。



這對(duì)于樣式維護(hù)來說是非常好的。它將樣式的所有關(guān)注點(diǎn)分離到單個(gè)組件上。

組織事件 (Event switch)

當(dāng)我們?cè)趯懯录幚砗瘮?shù)的時(shí)候,通常會(huì)使用 handle{事件名字} 的命名方式。

handleClick(e) { /* do something */ }

當(dāng)需要添加很多事件處理函數(shù)的時(shí)候,這些函數(shù)名字會(huì)顯得很重復(fù)。這些函數(shù)的名字并沒有什么價(jià)值,因?yàn)樗鼈冎淮砹艘恍﹦?dòng)作或者函數(shù)。

handleClick() { require("./actions/doStuff")(/* action stuff */) }
handleMouseEnter() { this.setState({ hovered: true }) }
handleMouseLeave() { this.setState({ hovered: false }) }

可以考慮寫一個(gè)事件處理函數(shù)來根據(jù)不同的 event.type 來組織事件。

handleEvent({type}) {
  switch(type) {
    case "click":
      return require("./actions/doStuff")(/* action dates */)
    case "mouseenter":
      return this.setState({ hovered: true })
    case "mouseleave":
      return this.setState({ hovered: false })
    default:
      return console.warn(`No case for event type "${type}"`)
  }
}

另外,對(duì)于簡(jiǎn)單的組件,你可以在組件中使用箭頭函數(shù)直接調(diào)用導(dǎo)入的動(dòng)作或者函數(shù)

someImportedAction({ action: "DO_STUFF" })}

在遇到性能問題之前,不要擔(dān)心性能優(yōu)化。真的不要

布局組件 (Layout component)

布局組件表現(xiàn)為一些靜態(tài) DOM 元素的形式。它們一般并不需要經(jīng)常更新。

就像下面的這個(gè)組件一樣,兩邊各自渲染了一個(gè) children。

}
  rightSide={}
/>

我們可以優(yōu)化這個(gè)組件。

HorizontalSplit 組件是兩個(gè)子組件的父元素,我們可以告訴組件永遠(yuǎn)都不要更新

class HorizontalSplit extends React.Component {
  shouldComponentUpdate() {
    return false;
  }

  render() {
    
      
{this.props.leftSide}
{this.props.rightSide}
} }
容器組件 (Container component)

「容器用來獲取數(shù)據(jù)然后渲染到子組件上,僅僅如此?!埂狫ason Bonta

這有一個(gè) CommentList 組件。

const CommentList = ({ comments }) => (
  
    {comments.map(comment => (
  • {comment.body}-{comment.author}
  • ))}
);

我們可以創(chuàng)建一個(gè)新組件來負(fù)責(zé)獲取數(shù)據(jù)渲染到上面的 CommentList 函數(shù)組件中。

class CommentListContainer extends React.Component {
  constructor() {
    super()
    this.state = { comments: [] }
  }

  componentDidMount() {
    $.ajax({
      url: "/my-comments.json",
      dataType: "json",
      success: comments =>
        this.setState({comments: comments});
    })
  }

  render() {
    return 
  }
}

對(duì)于不同的應(yīng)用上下文,我們可以寫不同的容器組件。

高階組件 (Higher-order component)

高階函數(shù) 是至少滿足下列一個(gè)條件的函數(shù):

接受一個(gè)或多個(gè)函數(shù)作為輸入

輸出一個(gè)函數(shù)

所以高階組件又是什么呢?

如果你已經(jīng)用過 容器組件, 這僅僅是一些泛化的組件, 包裹在一個(gè)函數(shù)中。

讓我們以 Greeting 組件開始

const Greeting = ({ name }) => {
  if (!name) {
    return 
連接中...
; } return
Hi {name}!
; };

如果 props.name 存在,組件會(huì)渲染這個(gè)值。否則將展示「連接中...」。現(xiàn)在來添加點(diǎn)高階的感覺

const Connect = ComposedComponent =>
  class extends React.Component {
    constructor() {
      super();
      this.state = { name: "" };
    }

    componentDidMount() {
      // this would fetch or connect to a store
      this.setState({ name: "Michael" });
    }

    render() {
      return ;
    }
  };

這是一個(gè)返回了入?yún)榻M件的普通函數(shù)

接著,我們需要把 Greeting 包裹到 Connect

const ConnectedMyComponent = Connect(Greeting);

這是一個(gè)強(qiáng)大的模式,它可以用來獲取數(shù)據(jù)和給定數(shù)據(jù)到任意 函數(shù)組件 中。

狀態(tài)提升 (State hoisting)

函數(shù)組件 沒有狀態(tài) (就像名字暗示的一樣)。

事件是狀態(tài)的變化。

它們的數(shù)據(jù)需要傳遞給狀態(tài)化的父 容器組件

這就是所謂的「狀態(tài)提升」。

它是通過將回調(diào)從容器組件傳遞給子組件來完成的

class NameContainer extends React.Component {
  render() {
    return  alert(newName)} />;
  }
}

const Name = ({ onChange }) => (
   onChange(e.target.value)} />
);

Name 組件從 NameContainer 組件中接收 onChange 回調(diào),并在 input 值變化的時(shí)候調(diào)用。

上面的 alert 調(diào)用只是一個(gè)簡(jiǎn)單的演示,但它并沒有改變狀態(tài)

讓我們來改變 NameContainer 組件的內(nèi)部狀態(tài)。

class NameContainer extends React.Component {
  constructor() {
    super();
    this.state = { name: "" };
  }

  render() {
    return  this.setState({ name: newName })} />;
  }
}

這個(gè)狀態(tài) 被提升 到了容器中,通過添加回調(diào)函數(shù),回調(diào)中可以更新本地狀態(tài)。這就設(shè)置了一個(gè)很清晰邊界,并且使功能組件的可重用性最大化。

這個(gè)模式并不限于函數(shù)組件。因?yàn)楹瘮?shù)組件沒有生命周期事件,你也可以在類組件中使用這種模式。

受控輸入 是一種與狀態(tài)提升同時(shí)使用時(shí)很重要的模式

(最好是在一個(gè)狀態(tài)化的組件上處理事件對(duì)象)

受控輸入 (Controlled input)

討論受控輸入的抽象并不容易。讓我們以一個(gè)不受控的(通常)輸入開始。

當(dāng)你在瀏覽器中調(diào)整此輸入時(shí),你會(huì)看到你的更改。 這個(gè)是正常的

受控的輸入不允許 DOM 變更,這使得這個(gè)模式成為可能。通過在組件范圍中設(shè)置值而不是直接在 DOM 范圍中修改

顯示靜態(tài)的輸入框值對(duì)于用戶來說并沒有什么用處。所以,我們從狀態(tài)中傳遞一個(gè)值到 input 上。

class ControlledNameInput extends React.Component {
  constructor() {
    super();
    this.state = { name: "" };
  }

  render() {
    return ;
  }
}

然后當(dāng)你改變組件的狀態(tài)的時(shí)候 input 的值就自動(dòng)改變了。

return (
   this.setState({ name: e.target.value })}
  />
);

這是一個(gè)受控的輸入框。它只會(huì)在我們的組件狀態(tài)發(fā)生變化的時(shí)候更新 DOM。這在創(chuàng)建一致 UI 界面的時(shí)候非常有用。

如果你使用 函數(shù)組件 做為表單元素,那就得閱讀 狀態(tài)提升 一節(jié),把狀態(tài)轉(zhuǎn)移到上層的組件樹上。

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

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

相關(guān)文章

  • 前端資源系列(4)-前端學(xué)習(xí)資源分享&前端面試資源匯總

    摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...

    princekin 評(píng)論0 收藏0
  • 【搶先領(lǐng)】《React 學(xué)習(xí)之道》我們翻譯了一本最簡(jiǎn)單,且最實(shí)用的 React 實(shí)戰(zhàn)教程……

    摘要:學(xué)習(xí)之道簡(jiǎn)體中文版通往實(shí)戰(zhàn)大師之旅掌握最簡(jiǎn)單,且最實(shí)用的教程。前言學(xué)習(xí)之道這本書使用路線圖中的精華部分用于傳授,并將其融入一個(gè)獨(dú)具吸引力的真實(shí)世界的具體代碼實(shí)現(xiàn)。完美展現(xiàn)了的優(yōu)雅。膜拜的學(xué)習(xí)之道是必讀的一本書。 《React 學(xué)習(xí)之道》The Road to learn React (簡(jiǎn)體中文版) 通往 React 實(shí)戰(zhàn)大師之旅:掌握 React 最簡(jiǎn)單,且最實(shí)用的教程。 showIm...

    oneasp 評(píng)論0 收藏0
  • 程序員練級(jí)攻略(2018):前端性能優(yōu)化和框架

    摘要:,谷歌給的一份性能指南和最佳實(shí)踐。目前而言,前端社區(qū)有三大框架和。隨后重點(diǎn)講述了和兩大前端框架,給出了大量的文章教程和相關(guān)資源列表。我認(rèn)為,使用函數(shù)式編程方式,更加符合后端程序員的思路,而是更符合前端工程師習(xí)慣的框架。 showImg(https://segmentfault.com/img/bVbjQAM?w=1142&h=640); 這個(gè)是我訂閱 陳皓老師在極客上的專欄《左耳聽風(fēng)》...

    VEIGHTZ 評(píng)論0 收藏0
  • 程序員練級(jí)攻略(2018):前端性能優(yōu)化和框架

    摘要:,谷歌給的一份性能指南和最佳實(shí)踐。目前而言,前端社區(qū)有三大框架和。隨后重點(diǎn)講述了和兩大前端框架,給出了大量的文章教程和相關(guān)資源列表。我認(rèn)為,使用函數(shù)式編程方式,更加符合后端程序員的思路,而是更符合前端工程師習(xí)慣的框架。 showImg(https://segmentfault.com/img/bVbjQAM?w=1142&h=640); 這個(gè)是我訂閱 陳皓老師在極客上的專欄《左耳聽風(fēng)》...

    CoffeX 評(píng)論0 收藏0
  • 前端文檔收集

    摘要:系列種優(yōu)化頁(yè)面加載速度的方法隨筆分類中個(gè)最重要的技術(shù)點(diǎn)常用整理網(wǎng)頁(yè)性能管理詳解離線緩存簡(jiǎn)介系列編寫高性能有趣的原生數(shù)組函數(shù)數(shù)據(jù)訪問性能優(yōu)化方案實(shí)現(xiàn)的大排序算法一怪對(duì)象常用方法函數(shù)收集數(shù)組的操作面向?qū)ο蠛驮屠^承中關(guān)鍵詞的優(yōu)雅解釋淺談系列 H5系列 10種優(yōu)化頁(yè)面加載速度的方法 隨筆分類 - HTML5 HTML5中40個(gè)最重要的技術(shù)點(diǎn) 常用meta整理 網(wǎng)頁(yè)性能管理詳解 HTML5 ...

    jsbintask 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

hzx

|高級(jí)講師

TA的文章

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