React學習(3)-不可不知的JSX

react學習(3)-不可不知的JSX.png

前言

本篇內容,對上一節的補充javascript

  1. JSX中添加屬性有什麼要注意的?以及JSX中的子元素是怎麼操做的?html

  2. 組件的大小寫問題,使用拓展運算符,以及怎麼循壞遍歷一個對象java

  3. JSX中的prop指的是什麼?以及表單的labe應該要注意什麼?react

以上問題即便本身很清楚,可是否有時卻老是道不清,說不明?那麼讀完本文,就豁然開朗了編程

若是你想閱讀體驗更好,可戳連接,不可不知的JSX,內有視頻數組

JSX添加特定屬性

自定義標籤拓展了原生HTML標籤不具有的能力,最大的一個用處就是屬性傳值,標籤的屬性值,能夠是字符串,變量對象bash

例如:以下所示微信

const element = <div divIndex ="0"></div>
複製代碼

固然也可使用下面這種方式,是等價的,用一個大括號將變量包裹起來babel

const element = <div divIndex={"0"}></div>
複製代碼

至於更多插值表達式內容,你能夠看上一節的dom

這裏要提一下,在屬性中嵌入javascript表達式,不要在雙大括號外面加上引號,例如,下面的是錯誤的

const element = <div divIndex="{ variable }"></div>
複製代碼

也就是說,對於字符串或者雙大括號中的表達式,對於同一屬性,不能同時使用這兩種符號

注意

JSX語法是更接近Javascript而不是HTML,只是長得像而已,對於Reat中自定義組件的屬性名稱,使用camelCase駝峯式命名來定義屬性的名稱,例如:定義JSX裏的class屬性,classNamed而divindex變成divIndex

JSX中的子元素

在原生HTML標籤中,要是對於DOM結構樹熟悉的話,理解JSX的子元素也是比較容易的

原生HTML的標籤叫作節點,節點有節點屬性,以及節點的內容

若是一個標籤或者React組件沒有內容,你是可使用/>,單標籤來閉合的,就像XML語法同樣,例如以下所示

const element =  <img src={ user.avatarUrl} />
複製代碼

JSX標籤裏面可以包含不少個子元素

例如:以下所示

const element = (
    <div>
        <h1 title="我是子h1元素屬性的內容">我是子h1元素的節點內容</h1>
        <h2>歡迎關注微信itclanCoder公衆號</h2>
        <h3>川川是全宇宙最帥的小夥子</h3>
    </div>
)
複製代碼

包含在開始和結束標籤之間的 JSX 表達式內容將會被做爲特定屬性 props.children傳遞給外層組件

其中,有下面幾種不一樣的方法來傳遞子元素

字符串字面量

你能夠將字符串放在開始和結束標籤之間,此時props.children就只是該字符串,對於內置的HTML元素是頗有用的,但同時要注意怎麼接收這個內容

<MyComponent>itclanCoder</MyComponent>
複製代碼

上面的JSX,MyComponent的子元素內容是itclanCoder,能夠經過props.children來獲取,它是一個沒有轉移的字符串itclanCoder

JSX會移除首尾行以及空行,與標籤相鄰的空行都會被刪除,文本字符串之間的新航都會被壓縮一個空格

因此下面的這幾種寫法都是等價的

<div>itclanCoder</div>

<div>
  itclanCoder
</div>

<div>
  川川
  itclanCoder
</div>

<div>

  itclanCoder
</div>
複製代碼

JSX子元素嵌套

在React中,子元素容許由多個JSX元素組成,組件能夠嵌套組件,例如:以下所示

<MyContainer>
   <Header />
   <Navigator />
   <Aside />
   <Footer />
</MyContainer>
複製代碼

在React中,是能夠將不一樣類型的子元素混合在一塊兒的,這跟在之前寫HTML是同樣的

<div>
   七月的天好熱
   <ul>
      <li>item1</li>
      <li>item2</li>
      <li>item3</li>
   </ul>
</div>
複製代碼

在React組件中,render函數的return的返回值,能夠返回一個數組,例如:

render() {
    // return 後面是一個數組
    return [
      <div key="div1">div1</div>,
      <div key="div2">div2</div>,
      <div key='div3'>div3</div>
    ]
}
// 固然爲了更好的看得舒服些的,最好是定義一個變量的
render() {
    var aDiv = [
        <div key="div1">div1</div>,
      <div key="div2">div2</div>,
      <div key='div3'>div3</div>
    ]
    return aDiv;
}
複製代碼

javascript表達式做爲子元素

在插值表達式中,javascript表達式能夠被包裹在雙大括號{}中,如下兩種寫法都是等價的

<myComponent>川川</myComponent>
<myComponent>{'川川'}</myComponent>
複製代碼

至於這種寫法的具體實用:對於展現任意長度的列表就很是有用了的,渲染HTML列表

import React from 'react';  
import ReactDOM from 'react-dom';


class Item extends React.Component {
    constructor(props) {
        super(props);


    }

    render() {
        return (
           <ul>
               <li>{ this.props.message }</li>
           </ul>
        );
    }
}

class TodoLIst extends React.Component {
    constructor(props) {
        super(props);

        this.todos = ['起牀', '刷牙', '洗臉', '工做'];
    }

    render() {
        return (
            <div>
                {
                    this.todos.map((message) => <Item key = {message} message = { message } />)
                }
            </div>
        );
    }
}

const container = document.getElementById('root');

ReactDOM.render(<TodoLIst />, container);

複製代碼

效果以下所示

javascript表達式做爲子元素.png

函數做爲子元素

{}插值表達式內能夠能夠變量,字符串,普通HTML元素,甚至能夠是組件,還能夠是函數

import React from 'react';      // 引入react.js,經過import關鍵字實例化一個React對象
import ReactDOM from 'react-dom'; 
import { tsPropertySignature } from '@babel/types';

function Repeat(props){
    let items = [];
    for(let i = 0; i < props.numTimes; i++) {
        items.push(props.children(i));
    }

    return <div>{ items }</div>
}

function ListOfTenFun() {
    return (
        <Repeat numTimes={ 10 }>
            {
                (index) => <div key={index}>我是列表 { index }</div>
            }
        </Repeat>
    )
}


const container = document.getElementById('root');

ReactDOM.render(<ListOfTenFun />, container);
複製代碼

效果以下所示:

函數做爲子元素列表.png

上面使用的是兩個函數組件,組件裏面是能夠嵌套另外一組件的,而且屬性值能夠經過props拿到

也說明了,你是能夠將任何東西做爲子元素傳遞給自定義的組件的, 只要該組件渲染以前可以被轉換成React理解的對象,它能夠用於拓展JSX

自定義的組件必須是大寫字母開頭

一般來講,若是在React中小寫字母開頭的html標籤,稱爲普通元素,它是原生HTML內置的元素(也能夠視爲爲組件),例如:<div>``<span>``<a>會被React轉化生成相應的字符串'div','span'傳遞給React.createElement做爲參數

大寫字母開頭的元素,咱們將它視爲自定義的組件,例如<MyButton />,其實它最終也會被React.createElement函數做爲轉化

使用大寫字母開頭命名自定義組件,這是一種約定俗成的規定,本質上它就是一構造函數,是爲了區別普通函數的

JSX標籤的第一部分指定了React元素的類型

凡是大寫字母開頭的JSX標籤元素,就意味着它們是React組件

若是你定義的一個組件首字母是小寫,react就會當作一個普通元素來處理,而原生HTML標籤並無把你自定義的元素概括進去,它是會報錯的

例如:以下所示

import React from 'react';    
import ReactDOM from 'react-dom'; 
import { tsPropertySignature } from '@babel/types';

// 如下是定義的函數組件,首字母小寫,這個是不正確的
function button(props) {
    return (
        <div>
            <button>{ props.content }</button>
        </div>
    )
}

function OutButton(){
    return (
        <Button content="按鈕" />
    );
}

const container = document.getElementById('root');

ReactDOM.render(<OutButton />, container);

// 正確的寫法
function Button(props) {
    return (
        <div>
            <button>{ props.content }</button>
        </div>
    )
}



ReactDOM.render(<OutButton />, container);
複製代碼

雖然錯誤的寫法不會報錯,它會將button認爲是一個html普通的標籤元素.

注意:

React必須在做用域內,JSX其實就是React.createElement函數的語法糖,React.createElement是更接近底層的API,因此React庫也必須包含在JSX代碼做用域內

引入React庫一部分目的就是爲了識別JSX語法的,這也是爲何只要你定義一個React組件時,要引入React庫的緣由

使用點(.)語法

有時候,在一個模塊中須要導出多個React組件時,在JSX中,使用點語法來引用一個React組件就很是方便了的 例如:以下所示

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


// MyButton組件
class MyButton extends Component {
   constructor(props){
      super(props);
   }

    render() {
        return (
            <Fragment>
                <button>{ this.props.btnContent }</button>
            </Fragment>
        );
    }
}

// MyInput組件
class MyInput extends Component{
    constructor(props) {
        super(props);

    }


    render() {
        return (
           <Fragment>
                <input value = { this.props.inputValue }  />
           </Fragment>
        );
    }
}

// 搜索部分
class SearchArea extends Component {

    render() {
        return (
           <Fragment>
                 <FormComponent.MyInput  inputValue="我是input組件輸入框內容" />
                 <FormComponent.MyButton btnContent="搜索按鈕" />
           </Fragment>
        );
    }
}

let FormComponent = {
    MyButton: MyButton,
    MyInput: MyInput
}
// 或者下面是Es6的一種等價寫法
let FormComponent = {
    MyButton,
    MyInput
}

const container = document.getElementById('root');

ReactDOM.render(<SearchArea />, container);

複製代碼

最終結果以下圖所示:

搜索按鈕.png

上面是把頁面中的某一個模塊(搜索),把與之相關的組件集中放在一個對象下管理,固然在實際開發中,因人而異了,要是看到別人這麼寫,也不要以爲怪怪的.

拓展運算符,屬性展開

對於拓展運算符(...),是一個很是有用的語法,若是你已經有了一個props對象,你可使用展開運算符...在JSX中傳遞整個props對象 以下所示:

function PersonA() {
     return (
         <Info name="川川" age="一個靠前排的90後帥小夥"  />
     );
}
// 上面的return後面的等價於
function personA() {
    const props = { name: "川川", age:"一個靠前排的90後帥小夥"}
    return (
      <Info { ...props } />
    );
    
}

function Info(props){
    return (
        <div>{ props.name }--{ props.age }</div>
    );
}

const container = document.getElementById('root');

ReactDOM.render(<PersonA  />, container);
複製代碼

小tips:如何將一對象進行輸出?

對於數組對象,能夠經過map方法進行輸出,然而假如是對象的話,倒是沒有這個方法的

具體使用的是Object.keys(對象)這個方法,它會返回一個數組,而且將對象的屬性名保存在一個數組中,若是是要獲取對象的屬性值,則能夠先轉數組,而後在使用數組的一些方法:例如map方法進行處理一下

var obj = {
name: "川川",
age: "你猜,小鮮肉一枚"
}
var getAttr = Object.keys(obj);
var getValue = Object.keys(obj).map((item) => obj[item]);
console.log(getAttr); // ["name", "age"]
console.log(getValue);// ["川川", "你猜,小鮮肉一枚"]
複製代碼

以下真實例子以下所示

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


class List extends Component {
    constructor(props) {
    super(props);
    // 下面是爲簡化代碼,綁定this 
    this.content = this.props.content;
    this.value = this.props.value;
}

render() {
return (
   <Fragment>
     <ul>
       {
         <li>{ this.content }-- { this.value }</li>
       }
     </ul>
   </Fragment>
);
}
}

class Person extends Component {
    constructor(props) {
    super(props);

    this.person = {
       name: "川川",
       age: "一個靠前排的90後帥小夥",
       desc: "歡迎關注微信itclanCoder公衆號"
    }
}

render() {
   let getPerson = Object.keys(this.person);
   return (
     <Fragment>
     {
       getPerson.map((item) => <List key = { item }
                           content = { item }
                           value = { this.person[item]} />
                )
     }
     </Fragment>
);
}
}

const container = document.getElementById('root');

ReactDOM.render(<Person />, container);
複製代碼

最終的效果以下所示:

Object.keys().png

JSX中的props

自定義組件定義的屬性稱爲prop,而屬性值稱爲prop值,因爲組件能夠定義多個屬性,因此能夠由多種方式在JSX中指定props

因爲JSX會被轉換爲React.createElement(組件元素, 屬性對象, 子元素),例如:以下JSX

const info = {
      title:"我是一個組件",
      number: 20
}
// 將info對象存儲到infoMessage變量屬性中,並傳給MyComponent組件
<MyComponent infoMessage = { info }>my component</MyComponent>
// 最終會被轉化爲
React.createElement(MyComponent, { infoMessage: info}, 'my component')
複製代碼

調用組件處,被稱爲父組件,而定義組件處,被稱爲子組件,對應的子組件想要接收父組件的值,用props去接收

label中的htmlFor

在原生html標籤中label與input的結合使用,增大鼠標的觸控範圍,起到加強用戶體驗的做用

for在JSX中應該被寫做htmlFor

<label htmlFor="firstname">First name:</label>
<input type="text" name="firstname" id="firstname">
複製代碼

結果以下所示

焦點htmlFor.gif

總結

本文主要講述在JSX中添加屬性的命名方式應是camelCase駝峯式命名來定義屬性的名稱,JSX中的子元素能夠是字符串,能夠嵌套,以及js表達式,函數均可以做爲子元素

而且在React中組件的定義以及調用處,組件名稱首字母必需要大寫,當導出多個React組件時,使用點語法來引用一個React組件

使用展開運算符 ...在JSX中傳遞整個props對象

某些時候,是一個很是有用的語法,另外,當遍歷要渲染的是一對象時,對象並無數組的一些方法,經過Object.keys()進行轉換,而後在使用.可以獲得對象的屬性以及屬性值

也知道JSX中的何爲prop,以及怎麼去接收props值

對於label與input使用時,要注意的一些地方.

固然對於JSX的相關知識學習暫且就這麼多了,仍然還有不少東西要學習的,編程是一門不斷探索的藝術,但願分享的這些的這些對你有些用

itclancoder二維碼.jpg
相關文章
相關標籤/搜索