自定义UI组件(表单组件,按钮组件,轻提示组件)

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('用后还未注册')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值