react組件化(一)

目前主流的框架有react/angular/vue。與angular不同,react是專注于用戶界面構(gòu)建,也就是mvvm中的view層,數(shù)據(jù)層(Model)和控制層(ViewModel)則是由社區(qū)提供的庫進(jìn)行構(gòu)建。在寫react的時(shí)候,記住一點(diǎn):react就是js。

react腳手架

npm install -g create-react-app --安裝腳手架
create-react-app my-app --使用腳手架創(chuàng)建react項(xiàng)目
cd my-app --進(jìn)入指定項(xiàng)目
npm start --啟動(dòng)項(xiàng)目

react基礎(chǔ)知識

jsx簡介

const element = <h1>Hello, world!</h1>;
如上變量,被成為JSX語言,是javascript的語法擴(kuò)展,Babel會(huì)把JSX轉(zhuǎn)譯成React.createElement函數(shù)調(diào)用。以下2種方式等價(jià)

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element=React.createElement(
'h1',
{className:'greeting'},
''Hello World!
)
  • jsx使用
    聲明一個(gè)變量name,在JSX中使用,寫在大括號中。在 JSX 語法中,你可以在大括號內(nèi)放置任何有效的 JavaScript 表達(dá)式。例如,2 + 2,user.firstNameformatName(user) 都是有效的 JavaScript 表達(dá)式。
const element=<p onClick={this.changeName} className='zhangsan' style={{coloe:red}}>{name}</p>

在下面的示例中,我們將調(diào)用 JavaScript 函數(shù) formatName(user) 的結(jié)果,并將結(jié)果嵌入到 <h1> 元素中。

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

const user = {
  firstName: 'Harper',
  lastName: 'Perez'
};

const element = (
  <h1>
    Hello, {formatName(user)}!
  </h1>
);

組件

react的核心就是組件,react組件分為函數(shù)類型組件和基于類的組件2種類型
函數(shù)類型的組件就是使用function創(chuàng)建的組件,基于類的組件是使用class關(guān)鍵詞創(chuàng)建的組件,組件的本質(zhì)也是函數(shù)。在react中組件名稱以大寫字母開頭。

  • 函數(shù)式組件寫法
 function Welcome1(props) {
  return <div>Welcome1, {props.name}</div>;
}
  • 基于類的組件寫法
class Welcome2 extends React.Component {
  render() {
    return <div>Welcome2, {this.props.name}</div>;
  }
}
  • 組件的調(diào)用
  class Welcome2 extends React.Component {
  render() {
    return <Welcome1 name='張三'></Welcome1>;
  }
}

state和props

在react中是單向數(shù)據(jù)流,頂級組件就有狀態(tài)state,通過props向下級組件進(jìn)行傳遞。下級組件為無狀態(tài)組件,只能使用props,不能夠修改狀態(tài)。在組件中,不能直接修改state,只能通過setState進(jìn)行修改組件狀態(tài)。組件狀態(tài)的修改是異步的,多次調(diào)用會(huì)合并成一次進(jìn)行組件狀態(tài)的修改。因此如果需要連續(xù)多次的修改狀態(tài)可以使用以下寫法

this.setState(()=>{
    date:new Date()
})
import React, { Component } from "react";

export default class StateTest extends Component {
  state = {
    counter: 1
  };

  componentDidMount() {
    //   請不要直接修改狀態(tài)值
    //   this.state.counter += 1;

    // 2.批量執(zhí)行
    // this.setState(obj, cb)
    // this.setState(fn, cb)
    this.setState(prevState => ({
      counter: prevState.counter + 1
    }));

    this.setState(prevState => ({
      counter: prevState.counter + 1
    }));

    this.setState(prevState => ({
      counter: prevState.counter + 1
    }));
  }

  render() {
    return <div>{this.state.counter}</div>;
  }
}

組件的嵌套

組件的嵌套以購物車的實(shí)例來進(jìn)行說明。直接上代碼。

  • 將函數(shù)和組件狀態(tài)以props的形式傳入下級組件。下級組件均為無狀態(tài)組件,只負(fù)責(zé)渲染,邏輯均在頂層組件
  • 函數(shù)的綁定與DOM不同的點(diǎn)在于,在DOM中綁定函數(shù)名小寫,在react中是駝峰命名法。在DOM中函數(shù)傳入字符串,在react中傳入函數(shù)體。
  • 在react的使用中,由于this指向問題,在定義函數(shù)時(shí),盡量使用箭頭函數(shù)的方式進(jìn)行定義
    reduceShopBook=()=>{}
    這樣this的指向f方為react實(shí)例。
    或者在初始化組件時(shí),使用以下方式來改變this指向
    this.reduceShopBook=this.reduceShopBook.bind(this)
  • 在jsx中可以map來循環(huán)數(shù)組
  • 在react中可以使用條件判斷和三元表達(dá)式來確定渲染的元素和組件。
// 三元表達(dá)式
const isLoggedIn = this.state.isLoggedIn;
 return (
   <div>
     The user is <b>{isLoggedIn ? 'currently' : 'not'}</b> logged in.
   </div>
 );

 // 使用If條件判斷
    const isLoggedIn = this.state.isLoggedIn;
    let button;

    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );

import React from 'react';
import logo from './logo.svg';
import './App.css';
class App extends React.Component{
   constructor(){
     super();
     this.reduceShopBook=this.reduceShopBook.bind(this)
     
   }
  
   state={
    books:[{
      name:'javascrip語言精粹',
      id:'1'
    },{
      name:'javascript高級程序設(shè)計(jì)',
      id:'2'
    }],
    shopBooks:[
      {
       name:'javascrip語言精粹',
       id:'1',
       count:1
      }
    ]
  }

   // 減少數(shù)目
   reduceShopBook(bookItem){
     const shopBooks=[...this.state.shopBooks];
     const bookIndex=shopBooks.findIndex((book)=>bookItem.id===book.id)
     if(shopBooks[bookIndex].count===1){ //去掉選項(xiàng)
         shopBooks.splice(bookIndex,1)
     }else{
       const newBook=Object.assign(shopBooks[bookIndex],{count:shopBooks[bookIndex].count-1})
        shopBooks.splice(bookIndex,1,newBook)
     }
     this.setState({shopBooks:shopBooks})
   }
   
   // 增加購物車中數(shù)目
   addShopBook=(bookItem)=>{
     let shopBooks=[...this.state.shopBooks];
     const bookIndex=shopBooks.findIndex((book)=>bookItem.id===book.id)
     if(bookIndex===-1){
       bookItem.count=1
       shopBooks=[...shopBooks,bookItem]
     }else{
       const book=Object.assign(shopBooks[bookIndex],{count:shopBooks[bookIndex].count+1})
     }
     this.setState({shopBooks:shopBooks})
   }

  // 渲染,調(diào)用下級組件。 將函數(shù)和組件狀態(tài)以props的形式傳入下級組件。修改組
   render(){
     const bookItems=<BookList books={this.state.books} addShopCart={this.addShopBook}></BookList>
     const shopcart=<Shopcart shopBooks={this.state.shopBooks} addShopBook={this.addShopBook} reduceShopBook={this.reduceShopBook}></Shopcart>
     const footer=<input type='button' value='確定' />
     return <div>
             {bookItems}
             {shopcart}
             </div>
   }
}
export default App;

/**
 * 書本列表 組件使用函數(shù)式組件,在下級組件中使用函數(shù)式組件,寫法較為簡單。
 * @param {*} props 
 */
function BookList(props){
  const listItems= props.books.map((bookItem)=>{
    return <li key={bookItem.id}>{bookItem.name} <input type='button' value='加入購物車' onClick={e=>props.addShopCart(bookItem)} /></li>
  })
  return <ul>{listItems}  </ul>
}

/**
 * 購物車列表 
 * @param {} props 
 */
function Shopcart(props){
   const shopItems=props.shopBooks.map((bookItem)=>{
     return <tr>
                <td>{bookItem.name}</td>
                <td>{bookItem.count}</td>
                <td><input type="button" value="+" onClick={e=>props.addShopBook(bookItem)}  /><input type='button' value='-' onClick={e=>props.reduceShopBook(bookItem)}/></td>
              </tr>
   })

   return <table>
         <thead><th>名稱</th><th>數(shù)目</th><th>操作</th></thead>       
         {shopItems}
        </table>
}
   
}

React中children的使用

有人說,咦,類似于vue中slot,在react中怎么沒有?不急,使用react中使用children屬性可實(shí)現(xiàn)哦。

  • React中的Children不一定是組件,它們可以使任何東西。從本質(zhì)上來講, props.children 可以使任何的類型,比如數(shù)組、函數(shù)、對象等等。
  • React提供了一系列的函數(shù)助手來使得操作children更加方便。
    兩個(gè)最顯眼的函數(shù)助手就是 React.Children.map 以及 React.Children.forEach 。它們在對應(yīng)數(shù)組的情況下能起作用,除此之外,當(dāng)函數(shù)、對象或者任何東西作為children傳遞時(shí),它們也會(huì)起作用。
  • 直接來個(gè)例子,封裝一個(gè)彈出框,外層樣式統(tǒng)一定義,內(nèi)容和樣式可定義。封裝一個(gè)過濾器
// 容器類組件 不需要知道狀態(tài)
// 作為容器 不需要關(guān)心狀態(tài)和邏輯
function Dialog(props){
  return <div style={{border:`1px solid ${props.color||'blue'}`}}>
             {props.children}
             {props.footer}
        </div>
}

// 使用封裝好的彈出框
function WelcomeDialog(props){
   return <Dialog {...props}>
          <p>hello world</p>
         </Dialog>
   
}
// 過濾器
function Filter(props){
  return<div>
   { 
    React.Children.map(props.children,(element)=>{
      if(element.type===props.type){
         return element
      }
   })
  }

  </div>
   
}
class  App extends React.Component{
 render(){
    const footer=<input type='button' value='確定' />
     return <div>
                    <WelcomeDialog color="green" footer={footer}></WelcomeDialog>
                  <Filter type='p'>
                      <p>1、p標(biāo)簽的使用</p>
                     <span>2、span標(biāo)簽</span>
                 </Filter>
            </div>
   }
}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 作為一個(gè)合格的開發(fā)者,不要只滿足于編寫了可以運(yùn)行的代碼。而要了解代碼背后的工作原理;不要只滿足于自己的程序...
    六個(gè)周閱讀 8,674評論 1 33
  • 40、React 什么是React?React 是一個(gè)用于構(gòu)建用戶界面的框架(采用的是MVC模式):集中處理VIE...
    萌妹撒閱讀 1,184評論 0 1
  • 深入JSX date:20170412筆記原文其實(shí)JSX是React.createElement(componen...
    gaoer1938閱讀 8,181評論 2 35
  • 以下內(nèi)容是我在學(xué)習(xí)和研究React時(shí),對React的特性、重點(diǎn)和注意事項(xiàng)的提取、精練和總結(jié),可以做為React特性...
    科研者閱讀 8,405評論 2 21
  • 1、什么是react React.js 是一個(gè)幫助你構(gòu)建頁面 UI 的庫。React.js 將幫助我們將界面分成了...
    谷子多閱讀 2,647評論 1 13

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