react實戰項目開發(2) react幾個重要概念以及JSX語法

前言

前面咱們已經學習了利用官方腳手架搭建一套能夠應用在生產環境下的React開發環境。那麼今天這篇文章主要先了解幾個react重要的概念,以及講解本文的重要知識JSX語法前端

React重要概念

【思想】
React 的核心思想是:封裝組件,各個組件維護本身的狀態和 UI,當狀態變動,自動從新渲染整個組件。

若是咱們使用react編寫的話,會把他拆分紅一個一個的小組件進行編寫方便管理複用性高,例如咱們把登陸拆分紅一個組件編寫,若是之後公司其它地方須要用到,那麼就能夠直接使用。react

看一段代碼感覺下:算法

import React, { Component } from 'react';
import { render } from 'react-dom';

class HelloMessage extends Component {
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}

// 加載組件到 DOM 元素 mountNode
render(<HelloMessage name="John" />, mountNode);

【組件】
React 應用都是構建在組件之上。瀏覽器

上面的 HelloMessage 就是一個 React 構建的組件,最後一句 render 會把這個組件顯示到頁面上的某個元素 mountNode 裏面,顯示的內容就是 <div>Hello John</div>。安全

props 是組件包含的兩個核心概念之一,另外一個是 state(這個組件沒用到)。能夠把 props 看做是組件的配置屬性,在組件內部是不變的,只是在調用這個組件的時候傳入不一樣的屬性(好比這裏的 name)來定製顯示這個組件。數據結構

【JSX】
從上面的代碼能夠看到將 HTML 直接嵌入了 JS 代碼裏面,這個就是 React 提出的一種叫 JSX 的語法,這應該是最開始接觸 React 最不能接受的設定之一,由於前端被「表現和邏輯層分離」這種思想「洗腦」過久了。但實際上組件的 HTML 是組成一個組件不可分割的一部分,可以將 HTML 封裝起來纔是組件的徹底體,React 發明了 JSX 讓 JS 支持嵌入 HTML 不得不說是一種很是聰明的作法,讓前端實現真正意義上的組件化成爲了可能。架構

好消息是你能夠不必定使用這種語法,後面會進一步介紹 JSX,到時候你可能就會喜歡上了。如今要知道的是,要使用包含 JSX 的組件,是須要「編譯」輸出 JS 代碼才能使用的。dom

【Virtual DOM】
當組件狀態 state 有更改的時候,React 會自動調用組件的 render 方法從新渲染整個組件的 UI。ide

固然若是真的這樣大面積的操做 DOM,性能會是一個很大的問題,因此 React 實現了一個Virtual DOM,組件 DOM 結構就是映射到這個 Virtual DOM 上,React 在這個 Virtual DOM 上實現了一個 diff 算法,當要從新渲染組件的時候,會經過 diff 尋找到要變動的 DOM 節點,再把這個修改更新到瀏覽器實際的 DOM 節點上,因此實際上不是真的渲染整個 DOM 樹。這個 Virtual DOM 是一個純粹的 JS 數據結構,因此性能會比原生 DOM 快不少。函數

【Data Flow】
「單向數據綁定」是 React 推崇的一種應用架構的方式。當應用足夠複雜時才能體會到它的好處,雖然在通常應用場景下你可能不會意識到它的存在,也不會影響你開始使用 React,你只要先知道有這麼個概念。

JSX語法

看以下變量的定義:若是是字符串應該添加引號,可是卻直接把DOM結構賦值給一個變量?什麼操做?這就是JSX

const element = <h1>Hello, world!</h1>;

它被稱爲 JSX, 一種 JavaScript 的語法擴展。 咱們推薦在 React 中使用 JSX 來描述用戶界面。JSX 看起來可能比較像是模版語言,但事實上它徹底是在 JavaScript 內部實現的。

【語法糖】
本質上講JSX只是爲React.createElement(component, props, ...children) 方法提供的語法糖

<MyButton color="blue" shadowSize={2}>
  Click Me
</MyButton>

等同於下面
React.createElement(
  MyButton,
  {color: 'blue', shadowSize: 2},
  'Click Me'
)

使用上篇文章搭建好的項目,並進行瘦身,而後新建一個組件JsxCom.js 而且引入到App.js中,代碼以下:

App.js

import React, { Component } from 'react';
import JsxCom from './JsxCom';

class App extends Component {
  render() {
    return (
      <div className="App">
        <JsxCom />
      </div>
    );
  }
}
export default App;

JsxCom.js

import React, { Component } from 'react';

class JsxCom extends Component {
  render() {
    return (
      <div className="JsxCom">
      </div>
    );
  }
}

export default JsxCom;

JSX 規則

如下幾點是剛開始寫React時比較容易忽視的規則

【制定React元素】
<JsxCom /> 首字母大寫的類型表示 JSX 標籤引用到一個 React 組件。這些標籤將會被編譯爲直接引用同名變量,因此若是你使用了 <JsxCom /> JSX 表達式,則 JsxCom 必須在做用域中。

【React 必須在做用域中】
因爲 JSX 編譯成React.createElement方法的調用,因此在你的 JSX 代碼中,React庫必須也始終在做用域中。也就是最上面必須引入React

【用戶定義組件必須首字母大寫】
當元素類型以小寫字母開頭時,它表示一個內置的組件,如 <div> 或 <span>,將致使字符串 'div' 或 'span' 傳遞給 React.createElement。 以大寫字母開頭的類型,如 <Foo /> 編譯爲 React.createElement(Foo),而且它正對應於你在 JavaScript 文件中定義或導入的組件。

【在運行時選擇類型】

const components = {
  photo: PhotoStory,
  video: VideoStory
};

function Story(props) {
  // 錯誤!JSX 標籤名不能爲一個表達式。
  return <components[props.storyType] story={props.story} />;
}

以下方式纔是正確的:
function Story(props) {
  // 正確!JSX 標籤名能夠爲大寫開頭的變量。
  const SpecificStory = components[props.storyType];
  return <SpecificStory story={props.story} />;
}

JSX 語法

【JSX的屬性(Props)表達式】
你能夠傳遞JavaScript 表達式做爲一個屬性,再用大括號{}括起來。例如,在這個 JSX 中:

<JsxCom foo={1+2+3}>

【在 JSX 中使用表達式】

直接看代碼

class JsxCom extends Component {
    user = {
        firstName: 'Harper',
        lastName: 'Perez'
    };

    formatName(user) {
        return user.firstName + ' ' + user.lastName;
    }

    render() {
      return (
        <div className="JsxCom">
          <h1>
            Hello, {this.formatName(this.user)}!
          </h1>
        </div>
      );
    }
}

分析:定義了一個字面量對象user,定義了一個函數formatName,輸出一個字符串。最後咱們在render函數中{this.formatName(this.user)} 使用該函數

【JSX中if語句和for語句的應用】

if 語句和 for 循環在 JavaScript 中不是表達式,所以它們不能直接在 JSX 中使用,可是你能夠將它們放在周圍的代碼中。例如:

function NumberDescriber(props) {
  let description;
  if (props.number % 2 == 0) {
    description = <strong>even</strong>;
  } else {
    description = <i>odd</i>;
  }
  return <div>{props.number} is an {description} number</div>;
}

【字符串常量】

<MyComponent message="hello world" />

<MyComponent message={'hello world'} />

【JSX 屬性】

// 使用引號來定義以字符串爲值的屬性
const element = <div tabIndex="0" className="hello"></div>;

// 使用表達式
const element = <img src={user.avatarUrl} />;

由於 JSX 的特性更接近 JavaScript 而不是 HTML , 因此 React DOM 使用 camelCase 小駝峯命名 來定義屬性的名稱,而不是使用 HTML 的屬性名稱。

例如,class 變成了 className,而 tabindex 則對應着 tabIndex。

【屬性默認爲「True」】
若是你沒有給屬性傳值,它默認爲 true。

<MyTextBox autocomplete />
等價於
<MyTextBox autocomplete={true} />

【展開屬性】
若是你已經有了個 props 對象,而且想在 JSX 中傳遞它,你可使用 ... 做爲「展開(spread)」操做符來傳遞整個屬性對象。下面兩個組件是等效的:

function App1() {
  return <Greeting firstName="Ben" lastName="Hector" />;
}

function App2() {
  const props = {firstName: 'Ben', lastName: 'Hector'};
  return <Greeting {...props} />;
}

【JSX中的子代】
在既包含開始標籤又包含結束標籤的 JSX 表達式中,這兩個標籤之間的內容被傳遞爲專門的屬性:props.children。

[1]字符串字面量
你能夠在開始和結束標籤之間放入一個字符串,則 props.children 就是那個字符串。這對於許多內置 HTML 元素頗有用。

<MyComponent>Hello world!</MyComponent>

這是有效的 JSX,而且 MyComponent 的 props.children 值將會直接是 "hello world!"

[2]嵌套React組件

<MyContainer>
  <MyFirstComponent />
  <MySecondComponent />
</MyContainer>

[3]JavaScript 表達式做爲子代
你能夠將任何 {} 包裹的 JavaScript 表達式做爲子代傳遞。例如,下面這些表達式是等價的:

<MyComponent>foo</MyComponent>

<MyComponent>{'foo'}</MyComponent>

[4]函數做爲子代
一般狀況下,插入 JSX 中的 JavaScript 表達式將被認做字符串、React 元素或這些的一個列表。然而,props.children 能夠像其它屬性同樣傳遞任何種類的數據,而不只僅是 React 知道如何去渲染的數據種類。例如,若是你有一個自定義組件,你能使其取一個回調做爲props.children:

// Calls the children callback numTimes to produce a repeated component
function Repeat(props) {
  let items = [];
  for (let i = 0; i < props.numTimes; i++) {
    items.push(props.children(i));
  }
  return <div>{items}</div>;
}

function ListOfTenThings() {
  return (
    <Repeat numTimes={10}>
      {(index) => <div key={index}>This is item {index} in the list</div>}
    </Repeat>
  );
}

傳遞給自定義組件的子代能夠是任何東西,只要該組件在 React 渲染前將其轉換成 React 可以理解的東西。這個用法並不常見,但當你想擴展 JSX 時可使用。

【布爾值、Null 和 Undefined 被忽略】
false、null、undefined 和 true 都是有效的子代,只是它們不會被渲染。下面的JSX表達式將渲染爲相同的東西:

<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>

相反,若是你想讓相似 false、true、null 或 undefined 出如今輸出中,你必須先把它轉換成字符串 :

<div>
  My JavaScript variable is {String(myVariable)}.
</div>

【JSX 防注入攻擊】

const title = response.potentiallyMaliciousInput;
// 直接使用是安全的:
const element = <h1>{title}</h1>;

React DOM 在渲染以前默認會 過濾 全部傳入的值。它能夠確保你的應用不會被注入攻擊。全部的內容在渲染以前都被轉換成了字符串。這樣能夠有效地防止 XSS(跨站腳本) 攻擊。

相關文章
相關標籤/搜索