本文將一步步介紹如何使用React或anu建立 一個彈出層。javascript
React時代,代碼都是要通過編譯的,咱們不少時間都耗在babel與webpack上。所以本文也介紹如何玩webpack與babel。html
咱們建立一個ui目錄,裏面添加一個package.json。內容以下,裏面已是儘可能減小babel插件的使用了。前端
{ "name": "ui", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "RubyLouvre", "license": "ISC", "devDependencies": { "babel-core": "^6.24.1", "babel-loader": "^6.4.1", "babel-preset-es2015": "^6.24.1", "babel-preset-react": "^6.16.0", "webpack": "^2.2.1" }, "dependencies": { "prop-types": "^15.5.10", "anujs": "^1.0.0" } }
若是你不想用anu,能夠改爲react與react-dom。java
"dependencies": { "prop-types": "^15.5.10" "react": "^15.5.4", "react-dom": "^15.5.4" }
anu自己沒有propTypes,而react最近的版本也把propTypes拆了出來,所以咱們須要獨立安裝prop-types這個包。node
webpack咱們緊隨時髦,使用2.0, 而babel則是一大堆東西。react
而後咱們在控制檯npm install
敲一下,會給咱們安裝上幾屏的依賴,下面只是展現了一部分。可見前端的發展多麼可怕,之前只是幾個JS文件就以爲很是臃腫了,如今幾百個習覺得常。儘管它們大部分是預處理JS的。這也爲React帶來巨大的門檻,門檻越高,工資越高。
webpack
而後 ui目錄下創建一個src目錄,裏面建toast.js。git
//第一部分,引入依賴與定義模塊內的全局變量 import React,{Component} from 'react'; import PropTypes from 'prop-types'; import ReactDOM from 'react-dom'; let singleton = null; const container = document.createElement('div'), defaultProps = { show: false }, propTypes = { /** * @property show * @description 是否顯示,默認false * @type Boolean * @default false * @skip */ show: PropTypes.bool }; document.body.appendChild(container); //第二部分,定義組件 class ToastReact extends Component { constructor(props) { super(props); this.state = { show: this.props.show, content: '', autoHideTime: 2000 }; this._timer = null; singleton = this; } shouldComponentUpdate(nextProps, nextState) { this.setState({ show: nextState.show }); if (!!this._timer) { clearTimeout(this._timer); this._timer = null; } this._timer = setTimeout(() => this.setState({ show: false }), nextState.autoHideTime); return true; } componentWillUnmount() { clearTimeout(this._timer); document.body.removeChild(container); } render() { const { show, content } = this.state; return ( <div className="yo-toast" style={{ display: show ? null : 'none' }} >{content}</div> ); } } ToastReact.propTypes = propTypes; ToastReact.defaultProps = defaultProps; ReactDOM.render(<ToastReact />, container); // 第三部分,一個代理對象,設置Toast的顯示隱藏函數 /** * Toast顯隱函數 * @returns {Object} */ export default { /** * @method show * @type Function * @description 打開組件,顯示傳入的內容 * @param {String} content 組件顯示的內容 * @param {Number} [autoHideTime] 內容顯示的持續時間,默認2000ms */ show(content = 'no content', autoHideTime = 2000) { singleton.setState({ content, autoHideTime, show: true }); return this; }, /** * @method hide * @type Function * @description 關閉正在顯示的組件 */ hide() { singleton.setState({ show: false }); return this; } };
整個文件分三部分,你們認真看註釋。之因此將彈層變成單例模式,所以窗口一般只存在一個彈層。存在多個彈層的狀況,大多數是設計不合理吧,好比說層上層。這種因爲在React時代,數據都保存在redux中,所以當層上層出現時,原彈層的用法輸入能夠保存到redux中,而後再改變彈層的內容,就能夠實現層上層的功能了。在jQuery時代,數據固化在dom裏,沒法剝離,纔出現這奇葩的狀況。github
而後 咱們再建一個app.js,裏面模擬業務線的同窗使用toast吧。web
import Tooltip from './coast'; var btn = document.querySelectorAll('.demo'); btn[0].addEventListener('click', function() { console.log('tooltip'); Tooltip.show('the tooltip autoHide after 2s'); }, false); btn[1].addEventListener('click', function() { console.log('tooltip 2') Tooltip.show('the tooltip autoHide after 3s', 3000); }, false); btn[2].addEventListener('click', function() { console.log('tooltip 3') var tip = Tooltip.show('the tooltip will be hidden before the default time 2s'); setTimeout(()=>tip.hide(), 1000); }, false);
而後在src的上一級目錄,即咱們原來ui 目錄建一個index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>tooltip demo</title> <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" /> <style> .yo-toast { position: fixed; top: 50%; left: 50%; -webkit-transform: translate(-50%, -50%); transform: translate(-50%, -50%); min-width: 1rem; max-width: 90%; z-index: 1500; height: 3rem; padding: 20px 10px; border-radius: .05rem; background-color: rgba(0, 0, 0, .5); color: #fff; } </style> </head> <body> <button>normal tooltip</button> <button>autohideTime tooltip</button> <button>hide() tooltip</button> </body> </html>
咱們準備在這個文件裏引用咱們的JS。JS必需要打包過的,babel處理過的。所以下面是重頭戲,創建一個webpack.config.js
const webpack = require("webpack"); const path = require("path"); const fs = require("fs"); module.exports = { context: __dirname, entry: { app: "./src/app.js" }, output: { path: __dirname + "/dist/", filename: "[name].js" }, module: { rules: [ { test: /\.jsx?$/, loader: "babel-loader", options: { presets: ["es2015", "react"] }, exclude: path.resolve(__dirname, "node_modules") } ] }, resolve: { //若是不使用anu,就能夠把這裏註釋掉 alias: { react: "anujs/dist/React.js", react: "anujs/dist/React.js", "react-dom": "anujs/dist/React.js" } } };
咱們須要在resolve配置項上設置別名,anu一個JS文件就包含了react與react-dom的功能,體積又少,最適合線上使用。
咱們敲下webpack命令,就發生成一個dist/app.js文件,而後 在index.html上引用它
<script src="./dist/app.js"></script>
最終效果圖
原本還想把業務中用到的babel helpers分離出來,最後可恥的失敗了,誰會麻煩給個參考項目給我。