React學(xué)習(xí)(3)-不可不知的JSX

前言

react學(xué)習(xí)(3)-不可不知的JSX.png

本篇內(nèi)容,對(duì)上一節(jié)的補(bǔ)充

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

  2. 組件的大小寫問題,使用拓展運(yùn)算符,以及怎么循壞遍歷一個(gè)對(duì)象

  3. JSX中的prop指的是什么?以及表單的labe應(yīng)該要注意什么?

以上問題即使自己很清楚,但是否有時(shí)卻總是道不清,說不明?那么讀完本文,就豁然開朗了

JSX添加特定屬性

自定義標(biāo)簽拓展了原生HTML標(biāo)簽不具備的能力,最大的一個(gè)用處就是屬性傳值,標(biāo)簽的屬性值,可以是字符串,變量對(duì)象

例如:如下所示

const element = <div divIndex ="0"></div>

當(dāng)然也可以使用下面這種方式,是等價(jià)的,用一個(gè)大括號(hào)將變量包裹起來

const element = <div divIndex={"0"}></div>

至于更多插值表達(dá)式內(nèi)容,你可以看上一節(jié)的

這里要提一下,在屬性中嵌入javascript表達(dá)式,不要在雙大括號(hào)外面加上引號(hào),例如,下面的是錯(cuò)誤的

const element = <div divIndex="{ variable }"></div>

也就是說,對(duì)于字符串或者雙大括號(hào)中的表達(dá)式,對(duì)于同一屬性,不能同時(shí)使用這兩種符號(hào)

注意

JSX語(yǔ)法是更接近Javascript而不是HTML,只是長(zhǎng)得像而已,對(duì)于Reat中自定義組件的屬性名稱,使用camelCase駝峰式命名來定義屬性的名稱,例如:定義JSX里的class屬性,classNamed而divindex變成divIndex

JSX中的子元素

在原生HTML標(biāo)簽中,要是對(duì)于DOM結(jié)構(gòu)樹熟悉的話,理解JSX的子元素也是比較容易的

原生HTML的標(biāo)簽叫做節(jié)點(diǎn),節(jié)點(diǎn)有節(jié)點(diǎn)屬性,以及節(jié)點(diǎn)的內(nèi)容

如果一個(gè)標(biāo)簽或者React組件沒有內(nèi)容,你是可以使用/>,單標(biāo)簽來閉合的,就像XML語(yǔ)法一樣,例如如下所示

const element =  <img src={ user.avatarUrl} />

JSX標(biāo)簽里面能夠包含很多個(gè)子元素

例如:如下所示

const element = (
    <div>
        <h1 title="我是子h1元素屬性的內(nèi)容">我是子h1元素的節(jié)點(diǎn)內(nèi)容</h1>
        <h2>歡迎關(guān)注微信itclanCoder公眾號(hào)</h2>
        <h3>川川是全宇宙最帥的小伙子</h3>
    </div>
)

包含在開始和結(jié)束標(biāo)簽之間的 JSX 表達(dá)式內(nèi)容將會(huì)被作為特定屬性 props.children傳遞給外層組件

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

字符串字面量

你可以將字符串放在開始和結(jié)束標(biāo)簽之間,此時(shí)props.children就只是該字符串,對(duì)于內(nèi)置的HTML元素是很有用的,但同時(shí)要注意怎么接收這個(gè)內(nèi)容

<MyComponent>itclanCoder</MyComponent>

上面的JSX,MyComponent的子元素內(nèi)容是itclanCoder,可以通過props.children來獲取,它是一個(gè)沒有轉(zhuǎn)移的字符串itclanCoder

JSX會(huì)移除首尾行以及空行,與標(biāo)簽相鄰的空行都會(huì)被刪除,文本字符串之間的新航都會(huì)被壓縮一個(gè)空格

所以下面的這幾種寫法都是等價(jià)的

<div>itclanCoder</div>

<div>
  itclanCoder
</div>

<div>
  川川
  itclanCoder
</div>

<div>

  itclanCoder
</div>

JSX子元素嵌套

在React中,子元素允許由多個(gè)JSX元素組成,組件可以嵌套組件,例如:如下所示

<MyContainer>
   <Header />
   <Navigator />
   <Aside />
   <Footer />
</MyContainer>

在React中,是可以將不同類型的子元素混合在一起的,這跟在以前寫HTML是一樣的

<div>
   七月的天好熱
   <ul>
      <li>item1</li>
      <li>item2</li>
      <li>item3</li>
   </ul>
</div>

在React組件中,render函數(shù)的return的返回值,可以返回一個(gè)數(shù)組,例如:

render() {
    // return 后面是一個(gè)數(shù)組
    return [
      <div key="div1">div1</div>,
      <div key="div2">div2</div>,
      <div key='div3'>div3</div>
    ]
}
// 當(dāng)然為了更好的看得舒服些的,最好是定義一個(gè)變量的
render() {
    var aDiv = [
        <div key="div1">div1</div>,
      <div key="div2">div2</div>,
      <div key='div3'>div3</div>
    ]
    return aDiv;
}

javascript表達(dá)式作為子元素

在插值表達(dá)式中,javascript表達(dá)式可以被包裹在雙大括號(hào){}中,以下兩種寫法都是等價(jià)的

<myComponent>川川</myComponent>
<myComponent>{'川川'}</myComponent>

至于這種寫法的具體實(shí)用:對(duì)于展示任意長(zhǎng)度的列表就非常有用了的,渲染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表達(dá)式作為子元素.png

函數(shù)作為子元素

{}插值表達(dá)式內(nèi)可以可以變量,字符串,普通HTML元素,甚至可以是組件,還可以是函數(shù)

import React from 'react';      // 引入react.js,通過import關(guān)鍵字實(shí)例化一個(gè)React對(duì)象
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);

效果如下所示:


函數(shù)作為子元素列表.png

上面使用的是兩個(gè)函數(shù)組件,組件里面是可以嵌套另一組件的,并且屬性值可以通過props拿到

也說明了,你是可以將任何東西作為子元素傳遞給自定義的組件的,
只要該組件渲染之前能夠被轉(zhuǎn)換成React理解的對(duì)象,它可以用于拓展JSX

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

通常來說,如果在React中小寫字母開頭的html標(biāo)簽,稱為普通元素,它是原生HTML內(nèi)置的元素(也可以視為為組件),例如:<div>``<span>``<a>會(huì)被React轉(zhuǎn)化生成相應(yīng)的字符串'div','span'傳遞給React.createElement作為參數(shù)

大寫字母開頭的元素,我們將它視為自定義的組件,例如<MyButton />,其實(shí)它最終也會(huì)被React.createElement函數(shù)作為轉(zhuǎn)化

使用大寫字母開頭命名自定義組件,這是一種約定俗成的規(guī)定,本質(zhì)上它就是一構(gòu)造函數(shù),是為了區(qū)別普通函數(shù)的

JSX標(biāo)簽的第一部分指定了React元素的類型

凡是大寫字母開頭的JSX標(biāo)簽元素,就意味著它們是React組件

如果你定義的一個(gè)組件首字母是小寫,react就會(huì)當(dāng)做一個(gè)普通元素來處理,而原生HTML標(biāo)簽并沒有把你自定義的元素歸納進(jìn)去,它是會(huì)報(bào)錯(cuò)的

例如:如下所示

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

// 以下是定義的函數(shù)組件,首字母小寫,這個(gè)是不正確的
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);

雖然錯(cuò)誤的寫法不會(huì)報(bào)錯(cuò),它會(huì)將button認(rèn)為是一個(gè)html普通的標(biāo)簽元素.

注意:

React必須在作用域內(nèi),JSX其實(shí)就是React.createElement函數(shù)的語(yǔ)法糖,React.createElement是更接近底層的API,所以React庫(kù)也必須包含在JSX代碼作用域內(nèi)

引入React庫(kù)一部分目的就是為了識(shí)別JSX語(yǔ)法的,這也是為什么只要你定義一個(gè)React組件時(shí),要引入React庫(kù)的原因

使用點(diǎn)(.)語(yǔ)法

有時(shí)候,在一個(gè)模塊中需要導(dǎo)出多個(gè)React組件時(shí),在JSX中,使用點(diǎn)語(yǔ)法來引用一個(gè)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組件輸入框內(nèi)容" />
                 <FormComponent.MyButton btnContent="搜索按鈕" />
           </Fragment>
        );
    }
}

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

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

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

最終結(jié)果如下圖所示:


搜索按鈕.png

上面是把頁(yè)面中的某一個(gè)模塊(搜索),把與之相關(guān)的組件集中放在一個(gè)對(duì)象下管理,當(dāng)然在實(shí)際開發(fā)中,因人而異了,要是看到別人這么寫,也不要覺得怪怪的.

拓展運(yùn)算符,屬性展開

對(duì)于拓展運(yùn)算符(...),是一個(gè)非常有用的語(yǔ)法,如果你已經(jīng)有了一個(gè)props對(duì)象,你可以使用展開運(yùn)算符...在JSX中傳遞整個(gè)props對(duì)象
如下所示:

function PersonA() {
     return (
         <Info name="川川" age="一個(gè)靠前排的90后帥小伙"  />
     );
}
// 上面的return后面的等價(jià)于
function personA() {
    const props = { name: "川川", age:"一個(gè)靠前排的90后帥小伙"}
    return (
      <Info { ...props } />
    );
    
}

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

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

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

小tips:如何將一對(duì)象進(jìn)行輸出?

對(duì)于數(shù)組對(duì)象,可以通過map方法進(jìn)行輸出,然而假如是對(duì)象的話,卻是沒有這個(gè)方法的

具體使用的是Object.keys(對(duì)象)這個(gè)方法,它會(huì)返回一個(gè)數(shù)組,并且將對(duì)象的屬性名保存在一個(gè)數(shù)組中,如果是要獲取對(duì)象的屬性值,則可以先轉(zhuǎn)數(shù)組,然后在使用數(shù)組的一些方法:例如map方法進(jìn)行處理一下

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);// ["川川", "你猜,小鮮肉一枚"]

如下真實(shí)例子如下所示

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


class List extends Component {
    constructor(props) {
    super(props);
    // 下面是為簡(jiǎn)化代碼,綁定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: "一個(gè)靠前排的90后帥小伙",
       desc: "歡迎關(guān)注微信itclanCoder公眾號(hào)"
    }
}

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值,由于組件可以定義多個(gè)屬性,所以可以由多種方式在JSX中指定props

由于JSX會(huì)被轉(zhuǎn)換為React.createElement(組件元素, 屬性對(duì)象, 子元素),例如:如下JSX

const info = {
      title:"我是一個(gè)組件",
      number: 20
}
// 將info對(duì)象存儲(chǔ)到infoMessage變量屬性中,并傳給MyComponent組件
<MyComponent infoMessage = { info }>my component</MyComponent>
// 最終會(huì)被轉(zhuǎn)化為
React.createElement(MyComponent, { infoMessage: info}, 'my component')

調(diào)用組件處,被稱為父組件,而定義組件處,被稱為子組件,對(duì)應(yīng)的子組件想要接收父組件的值,用props去接收

label中的htmlFor

在原生html標(biāo)簽中l(wèi)abel與input的結(jié)合使用,增大鼠標(biāo)的觸控范圍,起到增強(qiáng)用戶體驗(yàn)的作用

for在JSX中應(yīng)該被寫作htmlFor

<label htmlFor="firstname">First name:</label>
<input type="text" name="firstname" id="firstname">

結(jié)果如下所示


焦點(diǎn)htmlFor.gif

總結(jié)

本文主要講述在JSX中添加屬性的命名方式應(yīng)是camelCase駝峰式命名來定義屬性的名稱,JSX中的子元素可以是字符串,可以嵌套,以及js表達(dá)式,函數(shù)都可以作為子元素

并且在React中組件的定義以及調(diào)用處,組件名稱首字母必須要大寫,當(dāng)導(dǎo)出多個(gè)React組件時(shí),使用點(diǎn)語(yǔ)法來引用一個(gè)React組件

使用展開運(yùn)算符 ...在JSX中傳遞整個(gè)props對(duì)象

某些時(shí)候,是一個(gè)非常有用的語(yǔ)法,另外,當(dāng)遍歷要渲染的是一對(duì)象時(shí),對(duì)象并沒有數(shù)組的一些方法,通過Object.keys()進(jìn)行轉(zhuǎn)換,然后在使用.能夠得到對(duì)象的屬性以及屬性值

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

對(duì)于label與input使用時(shí),要注意的一些地方.

當(dāng)然對(duì)于JSX的相關(guān)知識(shí)學(xué)習(xí)暫且就這么多了,仍然還有很多東西要學(xué)習(xí)的,編程是一門不斷探索的藝術(shù),希望分享的這些的這些對(duì)你有些用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容