利用React/anu编写一个弹出层

react

本文将一步步介绍如何使用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分离出来,最后可耻的失败了,谁会麻烦给个参考项目给我。

以上是 利用React/anu编写一个弹出层 的全部内容, 来源链接: utcz.com/z/382319.html

回到顶部