react学习笔记(三)

十. 表单

10.1 受控组件

我们可以将表单写为受控组件:

class NameForm extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: ''
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
    }

    handleChange(event) {
        this.setState({
            value: event.target.value
        })
    }

    handleSubmit(event) {
        alert(this.state.value)
        event.preventDefault()
    }

    render() {
        return (
            
) } }

10.2 select 标签

在HTML中,select标签用来创建下拉列表标签。如下:


注意,由于selected属性的缘故,雪梨选项会被默认选中,但是在react中并不会使用selected属性,而是通过value把它变成受控组件。

class SelectComponent extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            value: ''
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
    }
    handleChange(event) {
        this.setState({
            value: event.target.value
        })
    }
    handleSubmit() {
        alert(this.state.value)
    }
    render() {
        return (
            
) } }

你可以将数组传递到value属性中,以支持select标签中选择多个选项


10.3 文件input 标签


因为它的value只读,所以它是React中的一个非受控组件

处理多个输入

当需要处理多个input的时候,我们可以给每个input设置一个 name 属性,然后根据 e.target.name 的值进行操作。

class MulInput extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            isGoing: false,
            guestNumbers: 0
        }
        this.handleChange = this.handleChange.bind(this)
        this.handleSubmit = this.handleSubmit.bind(this)
    }
    handleChange(event) {
        const target = event.target
        const name = target.name
        const value = target.type === 'checkbox' ? target.checked : target.value
        this.setState({
            [name]: value
        })
    }
    handleSubmit(event) {
        console.log(this.state.isGoing)
        console.log(this.state.guestNumbers)
        event.preventDefault()
    }
    render() {
        return (
            
) } }

十一. 状态提升

通常,多个组件需要反映相同的变化数据,这时我们建议将共享状态提升到共同的父组件去。

我们将创建一个给定水的温度判断水是否沸腾的温度计算器。

我们将从一个BoilingVerdict组件开始,它接受一个celsius温度作为prop,并根据该温度判断水是否沸腾返回不同的JSX

function BoilingVerdict(props) {
    if (props.celsius >= 100) {
        return 

我开辽

} else { return

我没开

} }

接下来创建一个名为Calculator的组件,它渲染一个用于输入温度的 并将它保存到 this.state.temperature中。

另外根据它当前输入值渲染BoilingVerdict组件

class Calculator extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            temperature: 0
        }
        this.handleChange = this.handleChange.bind(this)
    }
    handleChange(event) {
        this.setState({
            temperature: event.target.value
        })
    }
    render() {
        const temperature = this.state.temperature
        return (
            
Enter temperature in Celsius:
) } }

添加第二个输入框

在已有摄氏度输入框的基础上,我们提供华氏度输入框,并保持两个输入框数据同步

首先我们先把input框提取出来

const scaleNames = {
    c: "Celsius",
    f: "Fahrenheit"
}
class TemperatureInput extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            temperature: ""
        }
        this.handleChange = this.handleChange.bind(this)
    }
    handleChange(event) {
        this.setState({
            temperature: event.target.value
        })
    }
    render() {
        const scale = this.props.myType
        return (
            
Enter temperature in {scaleNames[scale]}:
) } } class Calculator extends React.Component { constructor(props) { super(props) this.state = { temperature: 0 } } render() { const temperature = this.state.temperature return (
) } }

编写转换函数

function toCelsius(fahrenheit) {
  return (fahrenheit - 32) * 5 / 9;
}

function toFahrenheit(celsius) {
  return (celsius * 9 / 5) + 32;
}

上面两个函数仅仅做值的转换,下面我们接收一个函数,它接受temperature和一个函数作为参数并返回一个字符串,我们将用它来依据一个输入框的值计算另一个输入框的值

function tryConvert(temperature, convert) {
    const input = parseFloat(temperature)
    if (Number.isNaN(input)) {
        return ''
    }
    const output = convert(input)
    const rounded = Math.round(output * 1000) / 1000
    return rounded.toString()
}

实现同步更新

首先,我们将TemperatureInput组件中的this.state.temperature替换为this.props.temperature

render() {
    temperature = this.props.temperature
    return (
        ...
    )
}

现在,当temperatureInput想更新时,需要调用this.props.onTemperatureChange()来进行更新:

handleChange(event) {
    this.props.onTemperatureChange(event.target.value)
}
const scaleNames = {
    c: "Celsius",
    f: "Fahrenheit"
}

// 华氏度转为摄氏度
function toCelsius(fahrenheit) {
    return (fahrenheit - 32) * 5 / 9;
}

// 摄氏度转为华氏度
function toFahrenheit(celsius) {
    return (celsius * 9 / 5) + 32;
}

// 传入一个温度和一个函数  根据是摄氏度还是华氏度对温度进行不同的转换
function tryConvert(temperature, convert) {
    const input = parseFloat(temperature)
    if (Number.isNaN(input)) {
        return ''
    }
    const output = convert(input)
    const rounded = Math.round(output * 1000) / 1000
    return rounded.toString()
}

class TemperatureInput extends React.Component {
    constructor(props) {
        super(props)
        this.handleChange = this.handleChange.bind(this)
    }
    handleChange(event) {
        this.props.onTemperatureChange(event.target.value)
    }
    render() {
        const scale = this.props.myType
        return (
            
Enter temperature in {scaleNames[scale]}:
) } } class Calculator extends React.Component { constructor(props) { super(props) this.state = { temperature: 0, scale: 'c' } this.handleCelsiusChange = this.handleCelsiusChange.bind(this) this.handleFahrenheitChange = this.handleFahrenheitChange.bind(this) } handleCelsiusChange(temperature) { this.setState({temperature,scale: 'c'}) } handleFahrenheitChange(temperature) { this.setState({temperature,scale: 'f'}) } render() { const scale = this.state.scale const temperature = this.state.temperature const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature return (
) } }
  1. 首先,我们改变了 摄氏度input 的值,触发TemperatureInput组件的onChange事件

  2. TemperatureInput组件的onChange事件触发 this.props.onTemperatureChange(event.target.value)并传入了一个摄氏度温度

  3. 然后触发了 Calculator组件中的onTemperatureChange事件

  4. 事件对state进行了设置 this.setState({temperature,scale: 'c'})

  5. Calculator组件中的state改变了 会触发 render() 方法

  6.  render() {
         const scale = this.state.scale
         const temperature = this.state.temperature
         const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature
         const fahrenheit  = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature
         return (
             
    ) }

从而根据摄氏度的值得到了新的华氏度的值,华氏度input组件this.props.temperature 的值进行了改变,华氏度input框的值也跟着改变

十二. 组合 && 继承

React有十分强大的组合模式。我们推荐使用组合而非继承的方式来实现组件之间的代码重用

你可能感兴趣的:(react学习笔记(三))