利用React/anu編寫一個彈出層


 

本文將一步步介紹如何使用React或anu創建 一個彈出層。

React時代,代碼都是要經過編譯的,我們很多時間都耗在babel與webpack上。因此本文也介紹如何玩webpack與babel。

我們創建一個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。

  "dependencies": { "prop-types": "^15.5.10" "react": "^15.5.4", "react-dom": "^15.5.4" }

anu本身沒有propTypes,而react最近的版本也把propTypes拆了出來,因此我們需要獨立安裝prop-types這個包。

webpack我們緊隨時髦,使用2.0, 而babel則是一大堆東西。

然后我們在控制台npm install敲一下,會給我們安裝上幾屏的依賴,下面只是展示了一部分。可見前端的發展多么可怕,以前只是幾個JS文件就覺得非常臃腫了,現在幾百個習以為常。盡管它們大部分是預處理JS的。這也為React帶來巨大的門檻,門檻越高,工資越高。




然后 ui目錄下建立一個src目錄,里面建toast.js。


//第一部分,引入依賴與定義模塊內的全局變量 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里,無法剝離,才出現這奇葩的情況。

然后 我們再建一個app.js,里面模擬業務線的同學使用toast吧。


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分離出來,最后可恥的失敗了,誰會麻煩給個參考項目給我。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM