前面幾篇的做法,我都是直接引用 CDN 來操作。我們還有第二種方法可以 include React,就是透過第二篇介紹過的 Webpack,所以今天就來學學 Webpack + React 的應用。
在專案裡面的 package.json
檔案中,我們可以分別看到 devDependencies
和 dependencies
,這兩個差別在於:前面的有 dev,後面的沒有(廢話xD)。前面的 dev
指的是 development ,就是在開發時需要用到的素材,開發中我們需要 babel 幫我們轉譯 JSX 語法,也需要 Webpack 幫我們打包。而後者則是在 production 時需要用到的素材,這個時候我們不需要 babel 和 webpack,但我們仍然需要 React 專案才能執行。
我在這個專案裡面載的是 15.4.2
版本的 React,不想用最新版本的話可以用這種寫法去定義你要安裝的版本
$ npm install --save react@15.4.2 react-dom@15.4.2
安裝完畢 package.json
檔案中可以看到以下:
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-preset-react": "^6.16.0",
"html-webpack-plugin": "^2.25.0",
"webpack": "2.1.0-beta.25",
"webpack-dev-server": "^1.16.2"
},
"dependencies": {
"react": "^15.4.2",
"react-dom": "^15.4.2"
}
接下來透過
$ npm install
這行指令的作用是,去讀取每一行 dependencies,確認你取得所有素材的最新版本。
跑完之後我們可以再下這行指令
$ npm run serve
去看是否能順利運作~
若順利運作,會出現 compile 成功的訊息(最後一行)
在這中間你會發現一行 url,這行就是我的專案的網址:
http://localhost:8080/webpack-dev-server/
anniesnoopymdde-MacBook-Air:React-product-search anniesnoopymd$ npm run serve
> product-search@1.0.0 serve /Users/anniesnoopymd/Documents/React-product-search
> webpack-dev-server --watch
http://localhost:8080/webpack-dev-server/
webpack result is served from /
content is served from /Users/anniesnoopymd/Documents/React-product-search
Hash: c9d5c7cc533697a6e2a3
Version: webpack 2.1.0-beta.25
Time: 1771ms
Asset Size Chunks Chunk Names
build.js 2.58 kB 0 [emitted] main
index.html 684 bytes [emitted]
chunk {0} build.js (main) 13 bytes [entry] [rendered]
[0] ./app/index.js 13 bytes {0} [built]
Child html-webpack-plugin for "index.html":
chunk {0} index.html 542 kB [entry] [rendered]
[0] ./~/lodash/lodash.js 540 kB {0} [built]
[1] (webpack)/buildin/global.js 506 bytes {0} [built]
[2] (webpack)/buildin/module.js 548 bytes {0} [built]
[3] ./~/html-webpack-plugin/lib/loader.js!./app/index.html 1.02 kB {0} [built]
webpack: Compiled successfully.
環境都設定完畢之後,就開始今天的專案吧~
我先簡單畫一下這個產品搜尋應用程式的大架構,最上面有一個搜尋 bar,下面是一個個搜尋結果區塊。
打開 app/index.js
,我們可以開始寫我們的邏輯了!
不過有一點要注意,現在我們的應用程式還沒有引入 React 這個函式庫,因為我剛剛先試了一下
ReactDOM.render(<h1>Hello</h1>, document.getElementById('app'));
在 debugger 裡面發現出現 ReactDOM
沒有被定義的錯誤訊息
Uncaught ReferenceError: ReactDOM is not defined
因此,我們要透過 require
,把 React 和 ReactDOM 呼叫進來
var React = require('react');
var ReactDOM = require('react-dom');
現在我要創一個 Search component
class Search extends React.Component {
render(){
return(
<div className="search">
<div className="search-bar">
<input placeholder="search" />
</div>
<div className="results"></div>
</div>
)
}
}
我在這個 component 裡面放了 input
,現在頁面的樣子:
我先放入一個搜尋結果區塊
class Search extends React.Component {
render(){
return(
<div className="search">
<div className="search-bar">
<input placeholder="search" />
</div>
<div className="results">
<div className="in-stock">
<h2><a href="#">Toothpaste</a></h2>
<p>$2.99</p>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco labor</p>
</div>
</div>
</div>
)
}
}
大架構出來之後,我們就可以開始拆解它,把它分解成一個個 child component 優化程式碼的維護。
切 component 囉~像切蛋糕一樣(突然肚子餓了QQ)
我切了一塊 SearchBar
child component
class SearchBar extends React.component {
render (){
return(
<div className="search-bar">
<input placeholder="search" />
</div>
)
}
}
現在我要在 input
上面綁定 onChange
就像我上次做的氣球換色,也是透過 onChange
去觸發 function。因此我在 <input />
裡加上 {this.handleQuery.bind(this)}
<input onChange={this.handleQuery.bind(this)} placeholder="search" />
關於 bind 的用法,我無法透過我的言語來解釋⋯⋯在詳讀 Reactjs 30 天邊做邊學系列 這篇文章之後,我只能說感恩 Seafood,阿不是!是謝謝這位前輩寫的超詳細
我在 handleQuery function
寫了 console.log 測試看到底有沒有綁到
handleQuery(){
console.log("Hi~It's time to bed");
}
結果是 YESSSSSSSS,我輸入了 tooth 五個字,觸發了五次 Hi~It's time to bed
不過仔細看了一下,咦,It's time to bed
是到了睡覺時間的意思嗎xD
還好我看得懂英文。。。
好吧那我就乖乖聽它的話準備上床睡囉
各位高手晚安不要太拼XDD
專案連結 Github