Write less code, do more things!

文档

value&onChange

计数器

<Count value={number} onChange={(number)=>{}} />
Count = require("react-defaultvalue")(Count)

var React = require('react')
class Count extends React.Component {
    render() {
        const self = this
        return (
            <button
                onClick={() => {
                    self.props.onChange(self.props.value + 1)
                }} >
                {self.props.value}
            </button>
        )
    }
}
// 一行代码实现 defaultValue
Count = require('react-defaultvalue')(Count)
module.exports = Count

调用计数器(默认20)

<Count defaultValue={20} />

var ReactDOM = require('react-dom');
var React = require('react')
var Count = require('./Count.js')
class UncontrolledCount extends React.Component {
    render () {
        return (
            <Count defaultValue={20} />
        )
    }
}

ReactDOM.render(
    <UncontrolledCount />,
    document.getElementById('count-uncontrolled-demo')
)

受控计数器

<Count value={self.state.value} onChange={...} />

var ReactDOM = require('react-dom');
var React = require('react')
var Count = require('./Count.js')
class ControlledCount extends React.Component {
    constructor(props) {
        super(props)
        this.state = { value: 10 }
    }
    render () {
        const self = this
        return (
            <Count
                value={self.state.value}
                onChange={function (value) {
                    self.setState({
                        value: value
                    })
                }}
            />
        )
    }
}

ReactDOM.render(
    <ControlledCount />,
    document.getElementById('count-controlled-demo')
)

show&onChange

提示层

<Tooltip show={boolean} onChange={(number)=>{}}>message</Tooltip>
Tooltip = require("react-defaultvalue")(Tooltip, {input: "show"})

import React , { Component } from "react"
class Tooltip extends Component {
    render() {
        const self = this
        return (
            <div>
                <button
                    onClick={() => {
                        self.props.onChange(!self.props.show)
                    }}
                >Tooltip</button>
                {
                    self.props.show?
                    self.props.children:
                    false
                }
            </div>
        )
    }
}
// 一行代码实现 defaultValue
Tooltip = require('react-defaultvalue')(Tooltip, {input: "show"})
module.exports = Tooltip

调用提示层(非受控)

<Tooltip>

var ReactDOM = require('react-dom');
var React = require('react')
var Tooltip = require('./Tooltip')
class UncontrolledTooltip extends React.Component {
    render () {
        return (
            <div>
                <Tooltip>
                    message one
                </Tooltip>
                <Tooltip defaultShow={true} >
                    message two
                </Tooltip>
            </div>
        )
    }
}

ReactDOM.render(
    <UncontrolledTooltip />,
    document.getElementById('tooltip-uncontrolled-demo')
)

调用提示层(受控)

<Tooltip show={self.state.show} onChange={function(value){}} >

var ReactDOM = require('react-dom');
var React = require('react')
var Tooltip = require('./Tooltip')
class ControlledTooltip extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            show: false
        }
    }
    render () {
        const self = this
        return (
            <div>
                <Tooltip
                    show={self.state.show}
                    onChange={function(value) {
                        self.setState({
                            show: value
                        })
                    }}
                >
                    message controlled
                </Tooltip>
            </div>
        )
    }
}

ReactDOM.render(
    <ControlledTooltip />,
    document.getElementById('tooltip-controlled-demo')
)

value&onPick

菜单

<Menu value={string} onPick={(string)=>{}} />
Menu = require("react-defaultvalue")(Menu, {output: "onPick"})

import React , { Component } from "react"
class Menu extends Component {
    render() {
        const self = this
        return (
            <div>
                <strong>{self.props.value}</strong>
                {
                    self.props.list.map(function (value) {
                        return (
                            <button
                                key={value}
                                onClick={function() {
                                    self.props.onPick(value)
                                }}
                            >{value}</button>
                        )
                    })
                }
            </div>
        )
    }
}
Menu.defaultProps = {
    list: ['meat', 'juice', 'egg'],
    onPick:function (){}
}
// 一行代码实现 defaultValue
Menu = require('react-defaultvalue')(Menu, {output: 'onPick'})
module.exports = Menu

菜单(非受控)

<Menu defaultValue="egg" >

var ReactDOM = require('react-dom');
var React = require('react')
var Menu = require('./Menu')
class UncontrolledMenu extends React.Component {
    render () {
        const self = this
        return (
            <Menu defaultValue="egg" />
        )
    }
}

ReactDOM.render(
    <UncontrolledMenu />,
    document.getElementById('menu-uncontrolled-demo')
)

菜单(受控)

<Menu value={self.state.value} onPick={function(){}} >

var ReactDOM = require('react-dom');
var React = require('react')
var Menu = require('./Menu')
class ControlledMenu extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: 'egg'
        }
    }
    render () {
        const self = this
        return (
            <Menu
                value={self.state.value}
                onPick={function (value) {
                    self.setState({
                        value: value
                    })
                }}
            />
        )
    }
}

ReactDOM.render(
    <ControlledMenu />,
    document.getElementById('menu-controlled-demo')
)

input.default

有些组件的 defaultValue 也需要有默认值。例如:

提示文字

业务需求是提示文字默认是显示的

import React , { Component } from "react"
class Tip extends Component {
    render() {
        const self = this
        return (
            <div>
                <button
                    onClick={function () {
                        self.props.onChange(!self.props.show)
                    }}
                >
                提示:
                {
                    self.props.show?
                    self.props.children:
                    false
                }
                </button>

            </div>
        )
    }
}
Tip = require('react-defaultvalue')(Tip, {
    // input: 'show' 中 `'show'` 改为对象
    input: {
        key: 'show',
        default: true
    }
})
module.exports = Tip

通过配置 {key: 'show', default: true} 设置 defaultShow 的默认值

提示文字(非受控)
var ReactDOM = require('react-dom');
var React = require('react')
var Tip = require('./Tip.js')
class UncontrolledTip extends React.Component {
    render () {
        return (
            <div>
                初始显示:<Tip>message</Tip>
                初始隐藏:<Tip defaultShow={false}>message</Tip>
            </div>
        )
    }
}

ReactDOM.render(
    <UncontrolledTip />,
    document.getElementById('tip-uncontrolled-demo')
)

output.sync

某些控件的输出(output)会包括很多信息,不适合直接将 output 函数的第一个参数 , event.target.value , event.target.checked 作为 输入(input) 保存。

例如:

<DatePicker
    value="2012-11-11"
    onChange={function (value) {
        /*
            value = {
                date: '2012-11-11',
                time: 1527406198844
            }
        */
    }}
/>

虽然我们在组件规范:输入输出中提供了更好的接口设计方法。但如果你依然要设计成

{
    date: '2012-11-11',
    time: 1527406198844
}

这种形式,或者这个组件是第三方的你无法修改。那么可以使用 output.sync 自定义返回值。

DatePicker 这个例子更好的接口设计不返回 value.time, value 的内容就是字符串 "2012-11-11"

日期选择
import React , { Component } from "react"
class DatePicker extends Component {
    constructor (props) {
        super(props)
        const self = this
        self.state = {

        }
    }
    render() {
        const self = this
        return (
            <input
                type="date"
                value={self.props.value}
                onChange={function (e) {
                    self.props.onChange({
                        date: e.target.value,
                        time: new Date(e.target.value).getTime()
                    })
                }}
            />
        )
    }
}
DatePicker  = require('react-defaultvalue')(DatePicker, {
    output: {
        key: 'onChange',
        sync: function (value) {
            return value.date
        }
    }
})
module.exports = DatePicker

日期选择(非受控)

<DatePicker defaultValue="2012-11-11"/>

var ReactDOM = require('react-dom');
var React = require('react')
var DatePicker = require('./DatePicker.js')
class UncontrolledDatePicker extends React.Component {
    render () {
        return (
            <DatePicker defaultValue="2012-11-11" />
        )
    }
}

ReactDOM.render(
    <UncontrolledDatePicker />,
    document.getElementById('datepicker-uncontrolled-demo')
)

日期选择(受控)

<DatePicker value={self.state.value} onChange={function(){}} />

var ReactDOM = require('react-dom');
var React = require('react')
var DatePicker = require('./DatePicker.js')
class ControlledDatePicker extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: '2018-11-11'
        }
    }
    render () {
        const self = this
        return (
            <DatePicker
                value={self.state.value}
                onChange={function (value) {
                    self.setState({
                        value: value.date
                    })
                }}
            />
        )
    }
}

ReactDOM.render(
    <ControlledDatePicker />,
    document.getElementById('datepicker-controlled-demo')
)

multi-input-output

有些组件会有多个输入输出,且输入输出的值是不同的。所以无法合并成一个输入输出。例如带每页数量的 Paging

分页

<Paging page={1} perPage={10} onChange={} onChangePerPage={} />

import React , { Component } from "react"
class Paging extends Component {
    render() {
        const self = this
        return (
            <div>
                第:
                <select
                    value={self.props.page}
                    onChange={function (e) {
                        self.props.onChange(e.target.value)
                    }}
                >
                    <option value="1" >1</option>
                    <option value="2" >2</option>
                    <option value="3" >3</option>
                </select>
                页。
                每页显示:
                <select
                    value={self.props.pageSize}
                    onChange={function (e) {
                        self.props.onChangePageSize(e.target.value)
                    }}
                >
                    <option value="10" >10</option>
                    <option value="50" >50</option>
                    <option value="100" >100</option>
                </select></div>
        )
    }
}
Paging = require('react-defaultvalue')(Paging, {
    // 使用数组配置 多输入输出,但要注意对应顺序。
    input: ['page', 'pageSize'],
    output: ['onChange', 'onChangePageSize']
})
module.exports = Paging

input output 改为 Array 且对应顺序即可支持多输入输出。

Paging = require('react-defaultvalue')(Paging, {
    input: ['page', 'perPage'],
    output: ['onChange', 'onChangePerPage']
})

多输入输出也是支持 output.sync{key:"onChange", sync: function(){/*...*/}}

分页(非受控)

<Paging defaultPage={2} />

var ReactDOM = require('react-dom');
var React = require('react')
var Paging = require('./Paging')
class UncontrolledPaging extends React.Component {
    render () {
        const self = this
        return (
            <Paging defaultPage={2} defaultPageSize={50} />
        )
    }
}

ReactDOM.render(
    <UncontrolledPaging />,
    document.getElementById('paging-uncontrolled-demo')
)

分页(受控)

<Paging page={self.state.page} perPage={self.state.perPage} />

var ReactDOM = require('react-dom');
var React = require('react')
var Paging = require('./Paging')
class ControlledPaging extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            page: "2",
            pageSize: "50"
        }
    }
    render () {
        const self = this
        return (
            <Paging
                page={self.state.page}
                pageSize={self.state.pageSize}
                onChange={function (page) {
                    self.setState({
                        page: page
                    })
                }}
                onChangePageSize={function (pageSize) {
                    self.setState({
                        pageSize: pageSize
                    })
                }}
            />
        )
    }
}

ReactDOM.render(
    <ControlledPaging />,
    document.getElementById('paging-controlled-demo')
)

Github
react-defaultvalue - 项目源码
相关站点
component-spec - 组件规范
module - 开源项目脚手架
onface.live - 资源集合