1.自定义表单组件
components/myinput/index.jsx 定义组件
import React from 'react';
class Com extends React.Component {
render () {
let placeholder = this.props.placeholder || '请输入提示信息' // 表单的提示信息
let type = this.props.type || 'text' // 表单的类型(text,password, radio, checkbox 等)
let clear = this.props.clear || false // 表单后面是否有清除按钮(也就是下面的button)
let label = this.props.label || '标题' // 表单前面的标题,例如:姓名:
let errortip = this.props.errortip || '' // 提示的错误信息
return (
<div className="inputbox">
// 前面的标题
<label>{label}</label>
<input type={type} placeholder={ placeholder } value={ this.props.value} onChange={ (event) => {
this.props.onChange(event.target.value)
}}/>
// 清除功能
{ clear && this.props.value.length > 0 ? <button onClick={() => {
this.props.onChange('')
}}>x</button> : ''}
// 提示的错误信息
<p>{errortip}</p>
</div>
)
}
}
export default Com;
views/login/index.jsx里调用组件
// 引入组件
import Myinput from '@/components/myinput';
// 调用组件
class Com extends React.Component {
constructor (props) {
super(props)
this.state = {
tel: '12312312312',
telerrortip: 'ok',
password: '123456',
passworderrortip: 'ok'
}
}
render () {
return (
<div className="content">
<Myinput
placeholder="请输入用户名"
clear
value={this.state.tel}
label = '手机号'
errortip={this.state.telerrortip}
onChange={(val) => {
// console.log('获取数据', val)
if(val.length === 0) {
this.setState({
telerrortip: '',
tel: val
})
} else if (val.length !== 11) {
this.setState({
telerrortip: '手机号码格式不正确',
tel: val
})
} else {
this.setState({
telerrortip: 'ok',
tel: val
})
}
}}
/>
<Myinput
type="password"
placeholder="请输入密码"
label = '密码'
clear
value={this.state.password}
errortip={this.state.passworderrortip}
onChange={ (val) => {
// console.log('获取数据', val)
let passworderrortip = ''
if (val.length === 0) {
passworderrortip = ''
} else if (val.length < 6) {
passworderrortip = '密码格式错误'
} else {
passworderrortip = 'ok'
}
this.setState({
passworderrortip,
password: val
})
}}
/>
</div>
)
}
}
export default Com;
2.自定义按钮组件
components/mybutton/index.jsx 定义组件
import React from 'react';
const Com = (props) => {
let value = props.value // 按钮的值
let type = props.type || 'default'; // 按钮类型
let bg = '' // 背景图
let activebg = '' // 点击后的背景图
let ftcolor = '' // 字体颜色
let size = props.size || 'normal' // 按钮大小
let paddVal = '' // padding值
let fontVal = '' // 字体大小
switch (size) { // 三种按钮大小
case 'normal':
paddVal = '10px 0'
fontVal = '16px'
break;
case 'small':
paddVal = '8px 0'
fontVal = '14px'
break;
case 'large':
paddVal = '12px 0'
fontVal = '18px'
break;
default:
break;
}
switch (type) {
case 'default':
bg = '#fff'
activebg = '#ccc'
ftcolor = '#666'
break;
case 'danger':
bg = '#f66'
activebg = '#d66'
ftcolor = '#fff'
break;
case 'success':
bg = '#9f9'
activebg = '#9D9'
ftcolor = '#fff'
break;
default:
break;
}
let disabled = props.disabled || false
let opacity = 1
disabled ? opacity = 0.4 : opacity = 1
return (
<div style={{ border: '1px solid #efefef', background: bg, textAlign: 'center', letterSpacing: '5px', color: ftcolor, padding: paddVal, fontSize: fontVal, opacity: opacity}} onClick = { () => {
if (!disabled) {
props.onClick()
}
}} onTouchStart={(event) => {
event.target.style.background = activebg
}} onTouchEnd={(event) => {
event.target.style.background = bg
}}>
{ value }
</div>
)
}
export default Com;
views/login/index.jsx 应用组件
<Mybutton
value='登录'
type="danger"
size='normal'
disabled = { this.state.telerrortip === '' || this.state.telerrortip === '手机号码格式不正确' || this.state.passworderrortip === '' || this.state.passworderrortip === '密码格式错误'}
onClick = {
() => {
console.log('按钮别点击了')
login({tel: this.state.tel, password: this.state.passworderrortip}).then(res => {
if (res.data.code === '10006') {
console.log('用户还未注册')
Mytoast.info('用后还未注册')
} else if (res.data.code === '10007') {
console.log('密码错误')
Mytoast.info('密码错误')
} else {
let userid = res.data.data.userid
let username = res.data.data.username
let token = res.data.data.token
localStorage.setItem('userid', userid)
localStorage.setItem('username', username)
localStorage.setItem('token', token)
}
})
}
}
/>
3.轻提示组件封装
3.1思路
生成一个新的div,添加(append)到document下,然后使用ReactDOM渲染该元素
创建一个Toast的类,因为需要类直接使用方法,所以创建相应的静态方法,直接调用
在方法调用前,清除定时器(如同节流),防止前面的定时器影响到后面弹出的toast的持续时间
3.2 es6中的静态方法
class Foo () {
static fn () {
console.log('es6的静态方法')
}
}
// Foo.fn() ----- 指向的类的本身 Toast.info()
class Foo () {
fn () {
console.log('es6的方法')
}
}
// new Foo().fn() ---- 指向的是类的实例 new Toast().info()
静态方法使用:在方法前加上static关键字
为什么使用静态方法:
阻止方法被实例继承,类的内部相当于实例的原型,所有在类中直接定义的方法相当于在原型上定义方法,都会被类的实例继承,但是使用static静态方法定义的不会被实例继承,而且可以被实例直接应用Foo.classMethod(),此时写成new Foo.classMethod()会提示不存在此方法
class Foo {
static bar () {
this.baz()
}
static baz () {
console.log('hello')
}
baz () {
console.log('world')
}
}
Foo.bar() // 'hello'
this指向类而不是类的实例
静态方法可以被子类继承,也可以被super调用
components/mytoast/index.jsx 定义组件
import React from 'react';
import ReactDOM from 'react-dom';
import './style.scss'
let timer = null // 全局定义定时器
class Toast {
static info (msg, timeout) { // 这里用到的是类的静态方法
msg = msg || 'info' // 提示信息
timeout = timeout || 2000 // 提示信息持续时长
init()
setTime(timeout)
ReactDOM.render(<span>{ msg }</span>, document.getElementById('toast'))
}
static danger (msg, timeout) {
msg = msg || 'danger'; // 提示信息
timeout = timeout || 2000; // 显示的时长
init();
setTime(timeout);
ReactDOM.render(<span className="danger">{msg}</span>, document.getElementById('toast'))
}
}
function init () {
// 每一次之前都要先清除定时器
clearTimeout(timer);
// 找到DOM节点,如果存在就直接显示,如果不存在就穿件一个div,然后append
let toast = document.getElementById('toast')
if (toast) {
toast.style.display = 'block'
} else {
let div = document.createElement('div')
// 给新创建的节点,自定义一个属性为id=toast
div.setAttribute('id', 'toast')
document.body.appendChild(div)
}
}
function setTime (timeout) {
timer = setTimeout (() => {
// 获取toast元素
let toast = document.getElementById('toast')
// 存在这一元素,两秒后display=none
if (toast) {
toast.style.display = 'none'
}
}, timeout)
}
export default Toast;
components/mytoast/style.scss 组件的简单样式
#toast {
position: fixed;
top: 40%;
left: 50%;
transform: translateX(-50%);
max-width: 40%;
background: #333;
z-index: 100;
padding: 5px 10px;
background: rgba(29, 29, 29, .73);
border-radius: 5px;
color: #fff;
text-align: center;
min-width: 100px;
pointer-events: none; //点击穿透
.info {
color: #fff;
}
.danger {
color: #0d0;
}
}
views/login/index.jsx 等组件的应用
Mytoast.info('用后还未注册')
Mytoast.danger('用后还未注册')