進度條

[ReactJS] 01. 為什麼要用React JS

從頭開始,從使用面與程式碼來介紹ReactJS

作者: 縱裕 更新日期:

此文章也有影片介紹,可以搭配影片一起學習!

01. 字串最常見的用途,輸入即改變的網頁Input實作 (getElementById 選擇器) (所屬課程)

02. 改寫ES5語法成React, 輸入即改變的網頁Input實作 (所屬課程)


以下正式開始文章


一般現在講到潮的代表,不外乎就是ReactJS與VueJS,所以喜歡與別人走不同路線的「進度條小編」之前寫了一篇。

 

多想一下,或許這個專案不需要用ReactJS。

 

用負面標題的方式簡單介紹了ReactJS

 

 

不過說實在的,當專案開始複雜,功能越來越多。再使用加上非同步AJAX撈取資料的情況越來越複雜。這時候基本功扎實的工程師就發現應該要搬出傳統的非同步解決方案。卻又發現JavaScript鬆散的設計讓實現上似乎沒那麼容易。

 

當然全世界高手這麼多,所以還是發明了許多解決方案。演進到目前,集大成的主流作品就是ReactJS 和 VueJS。當然隨著網站功能越來越複雜,就算是現在很多人使用,在不遠的未來被取代掉的可能性也還是很大。

 

本篇既然為使用面來介紹,現在就來講講真實的例子。在現在的網站上,最麻煩的大概就是即時性與互動性。以拍賣網站在後台上架一個商品。傳統的做法可能是一個 form 一頁就解決。

 

<form>
  <input name="product[name]">
  <input name="product[price]">
  <textarea name="product[description]">
  <button type="submit">送出</button>
</form>

 

當然會加上漂亮的CSS與其他商品應該要有的欄位。像是圖片,或是商品類別之類的。

 

不過現在的話可能就會想要做成。輸入時就可以看到最後在前台長出來的樣子。

就像是下面這樣。

 

標題:

價錢:


敘述:

 

 

 

 

 

 

你打的字自動會在Card顯示出來。

不過上面的功能是用純JavaScript做出來的,而且還只是ES5的版本。

 

 

程式碼如下:

<!-- HTML input-->

<div>
   <p>
     標題:<input id="post_example_name" name="product[name]" 
            placeholder="請輸入標題" 
            type="text" value="新標題" />
   </p>
   <p>
     價錢:<input id="post_example_price" min="0" 
            name="product[price]" 
            placeholder="請輸入價錢" 
            type="number" value="100" />
   </p>
    <p>
    敘述:<textarea id="post_example_description" 
           name="product[description]"></textarea>
    </p>
</div>
<!-- HTML card-->
<div class="_card">
  <div class="card-container">
    <div class="card-content">
      <h3 id="post_card_name">&nbsp;</h3>
      <h4 id="post_card_price" style="color:red;">&nbsp;</h4>
      <p id="post_card_description">&nbsp;</p>
    </div>
  </div>
</div>
<!-- javaScript -->
<script>

function initDynamicCard(){ 
  var cardNameElement = document.querySelector("#post_card_name"); 
  var cardPriceElement = document.querySelector("#post_card_price"); 
  var cardDescriptionElement = document.querySelector("#post_card_description"); 
  var exampleNameInput = document.querySelector("#post_example_name"); 
  var examplePriceInput = document.querySelector("#post_example_price"); 
  var exampleDescriptionInput = document.querySelector("#post_example_description"); 
  
  exampleNameInput.addEventListener('input', posts_36_card_update); 
  examplePriceInput.addEventListener('input', posts_36_card_update); 
  exampleDescriptionInput.addEventListener('input', posts_36_card_update); 

  function posts_36_card_update(){ 
    var name = exampleNameInput.value; 
    var price = examplePriceInput.value; 
    var description = exampleDescriptionInput.value; 
    cardNameElement.innerHTML = name; 
    cardPriceElement.innerHTML = price; 
    cardDescriptionElement.innerHTML = description; 
  } 

  posts_36_card_update(); 
} 

initDynamicCard();
</script>
<!-- css -->

<style>
._card{
  width: 300px;
  height: 230px;
  position: relative;
  overflow: hidden;
  float: left;
}


._card > .card-container{
  position: absolute;
  background-color: rgba(0, 0, 0, 0.3);
  color: white;
  text-align: left;
  margin: auto;
  bottom: 0;
  height: 100%;
  width: 100%;
}

._card > .card-container > .card-content{ 
  padding: 16px; 
}

._card > .card-container > .card-content > .price{ 
  color: red; 
}
</style>

 

 

這個範例就算是一個還算明顯的例子,上面的影片範例則是更簡單的內容。

這樣寫當然會動,不過他有一些麻煩點。

 

1. 每一個改變的欄位都要設定id,<input> 是可以靠attribute name來抓取。可是卡片上的欄位就沒辦法了。id有唯一性,所以如果同一頁裡有很多 card都可以被改,id 可能就會變成

#post_card1 , #post_card2

這樣子的流水號。程式碼一下變多很多,而且會出現字串組合("post_card" + number + "_name" 之類的程式碼),可讀性會突然下降不少。

 

 

2. 如果今天是使用AJAX來撈資料組成Table,就可能會出現大量的createElement 與 append 去動態組出card。

 

如果有維護過這樣的程式應該都知道痛苦,只是一個Table表都很容易出現40~50行程式碼,更不用說碰到寫得不好的程式。

   

 

如果改寫成React 來寫的話,雖然程式可能不會變短。但是就不需要id也可以實作,也不會碰到createElement 與 append。

接下來的程式碼現階段我們可能還看不懂,但是可以看出來的是HTML 與 JavaScript合起來了。

 

 

程式碼如下(Card CSS使用與JavaScript版一樣的版本):

(JSFiddle)

 

或是像上面一樣的文字版

<!-- html -->

<div id="demo">
</div>
<script src="js/main.js" type="text/javascript"></script>
<!-- jsx -->

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

class Card extends React.Component {   
  constructor(props) {     
   super(props);     
   this.state = {name: "新標題", price: 100, description: "description"};   
  }   
  handleNameChange(e){ this.setState({name: e.target.value});   } 
  handlePriceChange(e){ this.setState({price: e.target.value});   }   
  handleDescriptionChange(e){this.setState({description: e.target.value});   } 
  render() {  
    return(<div>  
      <div>     
      <p>標題:<input name="product[name]" 
                        placeholder="請輸入標題" type="text" 
                        value={this.state.name} 
                        onChange={this.handleNameChange.bind(this)}/></p>       
             
      <p>價錢:<input min="0" name="product[price]" 
                          placeholder="請輸入價錢" type="number" 
                          value={this.state.price} 
                          onChange={this.handlePriceChange.bind(this)} /></p>

      <p>敘述:<textarea name="product[description]" 
                         onChange={this.handleDescriptionChange.bind(this)}  
                         value={this.state.description}></textarea></p>
     </div>
     <div className="_card">           
       <div className="card-container">  
         <div className="card-content">               
           <h3>商品名稱:{this.state.name}</h3>               
           <h4 className="price">商品價格:{this.state.price}</h4>              
           <p>商品敘述:{this.state.description}</p>    
         </div>         
       </div>           
     </div>       
</div>)
}} 
ReactDOM.render(<Card />, document.querySelector("#demo"));

 

 

當然以這個例子感覺威力還不夠。

不過篇幅有限,所以以後再繼續介紹吧!

 


最後,如果你喜歡我們的文章,別忘了到我們的FB粉絲團按讚喔!!

Medium picture

縱裕

錄課程錄到快死掉了啊!!!