react組件化(一)

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

react腳手架

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

react基礎(chǔ)知識

jsx簡介

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

const element = (
  <h1 className="greeting">
    Hello, world!
  </h1>
);
const element=React.createElement(
'h1',
{className:'greeting'},
''Hello World!
)
  • jsx使用
    聲明一個變量name驹马,在JSX中使用,寫在大括號中竞漾。在 JSX 語法中,你可以在大括號內(nèi)放置任何有效的 JavaScript 表達式窥翩。例如业岁,2 + 2user.firstNameformatName(user) 都是有效的 JavaScript 表達式寇蚊。
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向下級組件進行傳遞。下級組件為無狀態(tài)組件俯邓,只能使用props骡楼,不能夠修改狀態(tài)。在組件中稽鞭,不能直接修改state鸟整,只能通過setState進行修改組件狀態(tài)。組件狀態(tài)的修改是異步的朦蕴,多次調(diào)用會合并成一次進行組件狀態(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ù)和組件狀態(tài)以props的形式傳入下級組件涉茧。下級組件均為無狀態(tài)組件,只負責渲染琴拧,邏輯均在頂層組件
  • 函數(shù)的綁定與DOM不同的點在于降瞳,在DOM中綁定函數(shù)名小寫,在react中是駝峰命名法蚓胸。在DOM中函數(shù)傳入字符串挣饥,在react中傳入函數(shù)體。
  • 在react的使用中沛膳,由于this指向問題扔枫,在定義函數(shù)時,盡量使用箭頭函數(shù)的方式進行定義
    reduceShopBook=()=>{}
    這樣this的指向f方為react實例锹安。
    或者在初始化組件時短荐,使用以下方式來改變this指向
    this.reduceShopBook=this.reduceShopBook.bind(this)
  • 在jsx中可以map來循環(huán)數(shù)組
  • 在react中可以使用條件判斷和三元表達式來確定渲染的元素和組件。
// 三元表達式
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è)計',
      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){ //去掉選項
         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屬性可實現(xiàn)哦。

  • React中的Children不一定是組件盈滴,它們可以使任何東西涯肩。從本質(zhì)上來講, props.children 可以使任何的類型巢钓,比如數(shù)組宽菜、函數(shù)、對象等等竿报。
  • React提供了一系列的函數(shù)助手來使得操作children更加方便铅乡。
    兩個最顯眼的函數(shù)助手就是 React.Children.map 以及 React.Children.forEach 。它們在對應數(shù)組的情況下能起作用烈菌,除此之外阵幸,當函數(shù)、對象或者任何東西作為children傳遞時芽世,它們也會起作用挚赊。
  • 直接來個例子,封裝一個彈出框济瓢,外層樣式統(tǒng)一定義荠割,內(nèi)容和樣式可定義。封裝一個過濾器
// 容器類組件 不需要知道狀態(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標簽的使用</p>
                     <span>2蔑鹦、span標簽</span>
                 </Filter>
            </div>
   }
}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末夺克,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子嚎朽,更是在濱河造成了極大的恐慌铺纽,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件哟忍,死亡現(xiàn)場離奇詭異狡门,居然都是意外死亡,警方通過查閱死者的電腦和手機锅很,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進店門其馏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人爆安,你說我怎么就攤上這事叛复。” “怎么了鹏控?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵致扯,是天一觀的道長。 經(jīng)常有香客問我当辐,道長抖僵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任缘揪,我火速辦了婚禮耍群,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘找筝。我一直安慰自己蹈垢,他們只是感情好,可當我...
    茶點故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布袖裕。 她就那樣靜靜地躺著曹抬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪急鳄。 梳的紋絲不亂的頭發(fā)上谤民,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機與錄音疾宏,去河邊找鬼张足。 笑死,一個胖子當著我的面吹牛坎藐,可吹牛的內(nèi)容都是我干的为牍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼碉咆!你這毒婦竟也來了抖韩?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤吟逝,失蹤者是張志新(化名)和其女友劉穎帽蝶,沒想到半個月后赦肋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體块攒,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年佃乘,在試婚紗的時候發(fā)現(xiàn)自己被綠了囱井。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡趣避,死狀恐怖庞呕,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情程帕,我是刑警寧澤住练,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站愁拭,受9級特大地震影響讲逛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岭埠,卻給世界環(huán)境...
    茶點故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一盏混、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惜论,春花似錦许赃、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至乾巧,卻和暖如春句喜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背卧抗。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工藤滥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人社裆。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓拙绊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子标沪,可洞房花燭夜當晚...
    茶點故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容

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