1. 程式人生 > >react v.16的新特性學習

react v.16的新特性學習

1、Fragment

新版本的render可以返回陣列、字串、react元件、數字、boolean值
v15.x必須要一個標籤來包裹
Before v16

return (
        <div>
            <label htmlFor="name">名字:</label>
            <input id="name" type="text" placeholder="請輸入名字"/>
            <button>搜尋</button>
        </div>
    );

When v16.0.0

return (
    [
        <label htmlFor="name">名字:</label>,
        <input id="name" type="text" placeholder="請輸入名字"/>,
        <button>搜尋</button>
    ]
);

Now v16.2.0

return (
    <React.Fragment>
       <label htmlFor="name">名字:</label>
<input id="name" type="text" placeholder="請輸入名字"/> <button>搜尋</button> </React.Fragment> );

片段(fragments) 可以讓你將子元素列表新增到一個分組中,並且不會在DOM中增加額外節點。key 是唯一可以傳遞給 Fragment 的屬性

return (
    <dl>
      {props.items.map(item => (
        // 沒有`key`,將會觸發一個key警告
        <React.Fragment
key={item.id}>
<dt>{item.term}</dt> <dd>{item.description}</dd> </React.Fragment> ))} </dl> );

簡明寫法<>

return (
    <>
       <label htmlFor="name">名字:</label>
       <input id="name" type="text" placeholder="請輸入名字"/>
       <button>搜尋</button>
    </>
);

DOM Fragment

const select = document.getElementById('select')
const values = [1, 2, 3]
const fragment = document.createDocumentFragment()
values.map(item => {
    const option = document.createElement('option')
    option.value = item
    option.innerHTML = `小明${item}號`
    fragment.appendChild(option)
})
select.appendChild(fragment)

2、Portals

Portals是reactjs16提供的官方解決方案,使得元件可以脫離父元件層級掛載在DOM樹的任何位置。
普通情況下,元件的render函式返回的元素會被掛載在它的父級元件上。
然而,有些元素需要被掛載在更高層級的位置。最典型的應用場景:當父元件具有overflow: hidden或者z-index的樣式設定時,元件有可能被其他元素遮擋,就可以考慮使用Portal使元件的掛載脫離父元件。
元件的掛載點雖然可以脫離父元件,但元件的事件通過冒泡機制仍可以傳給父元件。

<body>
    <div id="bd"></div>
    <div id="modal"></div>
</body>
render(
  <App>
    <SearchBox>
      <Modal>
        <div>模態框</div>
      </Modal>
    </SearchBox>
  </App>,
  document.getElementById('bd'),
  () => {
  console.log(arguments)
})

cl

ass App extends Component{
  constructor(options) {
    super(options)
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    alert('react component tree propagation!')
  }
  render() {
    return <div className="app" onClick={this.handleClick}>
      {this.props.children}
    </div>
  }
}
class Modal extends Component {
    constructor(options) {
      super(options)
    }
    render() {
      return createPortal(this.props.children, document.getElementById('modal'))
    }
  }
<div id="bd">
    <div class="app">
        <label for="name">名字:</label>
        <input type="text" id="name" placeholder="請輸入名字">
        <button>搜尋</button>
    </div>
</div>
<div id="modal">
    <div>模態框</div>
</div>
<App>
    <div className="app" onClick=bound handleClick()>
        <SearchBox>
            <labelhtmlFor="name">名字:</label>
            <inputid="name"type="text"placeholder="請輸入名字"></input>
            <button>搜尋</button>
            <Modal>
                <ReactPortal target=HTMLDivElement{…}>
                    <div>模態框</div>
                </ReactPortal>
            </Modal>
        </SearchBox>
    </div>
</App>

Before portals

ReactDom.render(reactChild, container, callback)

ReactDom.unmountComponentAtNode(container)


ReactDom.unstable_renderSubtreeIntoContainer(
    context,
    reactChild,
    domNode,
    callback
)

ReactDom.unmountComponentAtNode(container)


render: ReactMount._renderSubtreeIntoContainer(null, reactChild, container, callback )

unstable_renderSubtreeIntoContainer: ReactMount._renderSubtreeIntoContainer(context, reactChild, container, callback)

3、Error Boundaries

之前react在渲染過程中或者是生命週期內出現了致命的錯誤,react會從根元件上把所有的元件都解除安裝下來,以防止展現錯誤的資料,但這不是最好的使用者體驗。React 16修復了這一點,引入了Error Boundary的概念,中文譯為“錯誤邊界”,當某個元件發生錯誤時,我們可以通過Error Boundary捕獲到錯誤並對錯誤做優雅處理。(注:它並不能捕獲runtime所有的錯誤,比如元件回撥事件裡的錯誤,可以把它想象成傳統的try-catch語句)

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }
// 新增了componentDidCatch這個生命週期函式,它可以捕獲自身及子樹上的錯誤並對錯誤做優雅處理,包括上報錯誤日誌、展示出錯提示,而不是解除安裝整個元件樹。
  componentDidCatch(error, info) {
    // 錯誤代理元件的展示與否
    this.setState({ hasError: true });
    // 在這裡我們可以對錯誤進行記錄
    logErrorToMyService(error, info);
  }

  render() {
    if (this.state.hasError) {
      // 在這裡我們可以書寫自己想要展示的ui元件
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

上面的元件是當頁面中有錯誤時我們想要展示的效果,具體用法如下:

render(){
  return (
    <div>
      <ErrorBoundary>    // 外層元件我們定義的錯誤元件
        <Profile user={this.state.user} />     // 內層元件是我們將要監視的自定義元件
      </ErrorBoundary>
      <button onClick={this.onClick}>Update</button>
    </div>
  )
}

這個元件能夠不僅僅能夠監聽到本元件的錯誤,連同它下面的子元件的錯誤也可以監聽到

不能捕獲的錯誤

  • 事件處理
  • 非同步回撥
  • 服務端渲染
  • error boundary元件自身丟擲的錯誤(只能由父級捕獲)

react遇到未捕獲的錯誤會怎麼辦

對 React16 來說,一個未捕獲的錯誤會導致整個應用不能被掛載

4、setState傳入null時不會再觸發更新

之前的setState不管傳入什麼只要呼叫了這麼方法就會渲染

selectCity(e){
  const newValue = e.target.value;
  this.setState((state)=>{
    if(state.city===newValue){
      return null;
    }
    return {city:newValue}
  })
)

5、v16.0支援自定義的dom屬性

之前的版本對於自定義屬性react會在屬性前加上data-**來進行處理,現在對於部分屬性去除了這種寫法,擁抱了原生dom,這樣可以減少react的程式碼,提升了效能

6、其他

更好的伺服器端渲染:React 16的SSR被完全重寫,新的實現非常快,接近3倍效能於React 15,現在提供一種流模式streaming,可以更快地把渲染的位元組傳送到客戶端。

react v16採用了最新的技術“Fiber.”

React Server Side Rendering 解決 SPA 應用的 SEO 問題

相關推薦

react v.16特性學習

1、Fragment 新版本的render可以返回陣列、字串、react元件、數字、boolean值 v15.x必須要一個標籤來包裹 Before v16 return ( <div> <label

React 16 特性

2017年9月26日React 16釋出,通過官網和示例瞭解一下新特性。 React 16更新 新js環境要求 react16依靠Map和Set集合和requestAnimationFra

java 特性學習筆記

sets arp string get pen option ring true read java 1.7 Files.write(path,list,StandardCharsets.UTF_8,StandardOpenOption.APPEND); St

JDK7特性學習之 --- switch的表達式

bre image http 例如 style 之前 字符 深入理解 編譯錯誤   JDK7之前,switch中表達式只能是char、byte、short、int及其對應的包裝類和枚舉類型。JDK7之後java中新增加了String類型作為switch的表達式之一。   但

java8特性學習:stream與lambda

包含 term strong java statistic 管道 特定 getname java8新特性 Streams api 對 Stream 的使用就是實現一個 filter-map-reduce 過程,產生一個最終結果,或者導致一個副作用(side effect)

c++11 多線程特性學習 (1) 管理線程

his on() argc 等待 通過 運行 int 選擇 如果 1.基礎介紹  c++11中,線程是通過std::thread對象來開始的,用法為 #include<thread> //必須包含的頭文件 void do_work(){ std::c

Java8特性學習-總結

1. 介面的擴充套件方法 Java8允許給介面新增一個非抽象的方法,只需要使用default關鍵字即可,這個特徵又叫做擴充套件方法。 程式碼:定義Formula 介面,接口裡定義非抽象方法sqrt,並用default修飾 interface Formula { do

php7特性學習

1、標量型別宣告 在函式/方法的引數及返回值處宣告資料型別為某個具體的資料型別,則必須傳入或返回對應的資料型別,否則會報錯。 function inputint(int $a) { echo $a; } function returnArray(): array {

C++11特性學習筆記—使用花括號就地初始化

這個特性是真正極好的!非常好用且方便!降低工作量!      如果一個類有很多成員變數A,B,C,D...,而且有很多不同版本的建構函式c1,c2,c3....,每個不同的建構函式可能會選擇不同的成員

JDK8 併發特性學習 (一) CompletableFuture

JDK8 併發新特性學習 (一) CompletableFuture JDK 8 java.util.concurrent新增加的兩個介面和四個類 CompletableFutre.AsynchronousCompletionTask 一個沒有方法的裝飾介面,用來標識非

Tomcat 7 特性學習之一

Tomcat 7 Beta版本出來已經有段時間了,看了JavaEye上的朋友,還是有幾個非常勤奮每天都在學習的朋友,他們能夠每天學習,堅持下來,實屬不易,他們非常的年輕,有幾個,我還見過面,小夥子們的好學精神實在讓人敬佩。這個社會很浮躁,我自己也是這樣,尤其在杭州這種城市裡生

C11特性學習

#include <cstdio> #include <iostream> #include <Windows.h> //#define _AFXDLL  //#include "afx.h" #include <strsafe.h> #in

2019 年的 JavaScript 特性學習指南

昨天在瀏覽 Babel 網站時,看到它的 blog 有一篇新的文章,說 Babel 釋出了新的程式碼支援 class 的私有屬性和方法。 這著實讓我頭腦混亂,到底在哪可以瞭解到最新的規範?而這些規範又是否被支援?支援到什麼程度?完全沒有頭緒。 自從 ES6 規範釋出以來,帶來很多新的特性,而我們在消化這些

Java8特性學習-Stream的Reduce及Collect方法詳解

Stream的使用方法在http://blog.csdn.net/icarusliu/article/details/79495534一文中已經做了初步的介紹,但它的Reduce及Collect方法由於較為複雜未進行總結,現單獨對這兩個方法進行學習。 為簡化理

Kubernetes 1.6特性學習:RBAC授權

概述 Kuberntes中API Server的訪問控制過程圖示如下: 在Kubernetes中,授權(authorization)是在認證(authentication)之後的一個步驟。授權就是決定一個使用者(普通使用者或ServiceAccount)是否有權請

Java 8 特性——學習總結

Java 8 新特性  Java 9都快出來了,把Java 8學習一波,很多語言特性在別的語言中都見過,一些優秀的語言特性,好語言都會整合! 程式設計風格 Java8希望有自己的程式設計風格,並與Java7分開,以下展示以下兩者的區別。 package com.tenc

C++11特性學習筆記—final和override關鍵字

一、final關鍵字                為什麼c++現在才提供final這個關鍵字?很奇怪。             和Java一樣,c++中的final關鍵字是用來修飾一個函式,防止這個

Java8 特性學習

1、介面中的預設方法 Java8中允許介面中包含具有具體實現的方法,這種方法被稱為“預設方法”,使用default關鍵字修飾。 如: public interface MyInterface { String notDefault();

JDK8特性學習(一) Lambda表示式和函式式介面

Lambda表示式和函式式介面 剛進公司時,公司正處於由JDK7換用JDK8的時間短,之所以更換JDK版本,聽說是公司業務中需要用到JDK8的一些新特性。鑑於我現在也無事可做,姑且來學習總結一下JDK8的一些特性吧。水平有限,這篇勉強算是對他人部落格上零

list 集合排序,java8特性,學習一下

最近做一個專案,遇到了list<Entity>需要按時間倒敘排列發現Java8新特性封裝的比較好:例子:List<Entity> list = Lists.newArrayLis