進度條

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

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

作者: 縱裕 更新日期:

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

 

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

 

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

 

 

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

 

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

 

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

 

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

 

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

 

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

就像是下面這樣。

 

標題:

價錢:


敘述:

 

 

 

 

 

 

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

不過上面的功能是用jQuery做出來的。

 

 

程式碼如下:

<!-- 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 style="display: table;">
  <div class="_card">
    <div class="card-image">
       <img src="/uploads/course/card_image/4/large_JSwjQuery.png" /></div>
    </div>
    <div class="card-content">
      <div style="padding: 12px;">
        <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>
</div>
<!-- javaScript -->
<script>
  function posts_36_card_update(){
    $("#post_card_name").html("商品名稱:" + $("#post_example_name").val());
    $("#post_card_price").html("商品價格:" + $("#post_example_price").val());
    $("#post_card_description").html("商品敘述:" + $("#post_example_description").val());
  }
  posts_36_card_update();

  $("#post_example_name").on('input', posts_36_card_update);
  $("#post_example_price").on('input', posts_36_card_update);
  $("#post_example_description").on('input', posts_36_card_update);
</script>
<!-- css -->

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

._card > .card-image{
  position: absolute;
}

._card > .card-image img{
  width: 100%;
  height: 230px;
  vertical-align: bottom;
}

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

 

(這程式碼直接在文章裡面寫的,所以比較醜一點還請包涵。)

 

這個範例就算是一個還算明顯的例子。

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

 

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

#post_card1 , #post_card2

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

 

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

如果有維護過這樣的程式應該都知道痛苦,只是一個Table表都很容易出現40~50行程式碼,更不用說碰到寫得不好的程式。(當然使用jquery 的clone()可以偷機少寫些程式碼。)

   

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

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

不過這裡沒有用太多ES6 或是 ES7 的寫法,因為個人認為那是React讓人覺得很難學的原因之一。

 

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

 

<!-- html -->

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

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

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>       
      標題:<input is name="product[name]" 
                        placeholder="請輸入標題" type="text" 
                        value={this.state.name} 
                        onChange={this.handleNameChange.bind(this)}/>       
             
      價錢:<input is min="0" name="product[price]" 
                          placeholder="請輸入價錢" type="number" 
                          value={this.state.price} 
                          onChange={this.handlePriceChange.bind(this)} />

      敘述:<textarea is name="product[description]" 
                         onChange={this.handleDescriptionChange.bind(this)}  
                         value={this.state.description}>
           </textarea>

      <div is style={{"display":"table"}}>         
        <div is class="_card">           
          <div is class="card-image">             
            <img is src="/uploads/course/card_image/4/large_JSwjQuery.png" />                   
          </div>
          <div is class="card-content">       &               
            <h3>商品名稱:{this.state.name}</h3>               
            <h4 style={{"color": "red"}}>商品價格:{this.state.price}</h4>              
            <p>商品敘述:{this.state.description}</p>             
         </div>           
       </div>         
     </div>       
   </div>      
 </div>)
}} 
 ReactDOM.render(<Card />, document.getElementById("demo"));

 

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

不過篇幅有限,所以下一篇再繼續

 


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

Medium picture

縱裕

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