react组件
react组件的后缀名可以是js,也可以是jsx
- 需要配置webpack的解析器以及缺省的后缀名
- 重新调整代码结构
React props
- state 和 props 主要区别在于 props 是不可变的,而 state 可以根据用户的交互来改变。
- 组件本身自己用state, 组件之间使用props(vue中组件本身data,组件之间传值)
props的基本案例
父子组件的传值
- 父组件在调用子组件的地方,添加一个自定义的属性,属性的值就是你需要传递给子组件的值,如果属性的值是变量,boolean,number,需要使用 {}包裹
在子组件中 通过 this.props 获取到父组件传递过来的数据
如果传递的是一个变量
如果props需要要默认值呢(传则用传的,不传则用默认的)
如果传递的值需要 数据类型的校验
cnpm i prop-types -D
(React v15.5 版本后把数据类型检验单独的移动到 npm 包,减少核心库的体积)
报错时的信息
拓展-react15.5以前组件写法以及验证
// 这段代码不要在编辑器编写,编写无效 -- react版本
var title = 'hello react';
var MyTitle = React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired
},
render () {
return (
<div>{ this.props.title }</div>
)
}
})
ReactDOM.render(<MyTitle title={ tilte } />, document.getElementById('app'))
react props 完整验证规则
https://react.docschina.org/docs/typechecking-with-proptypes.html
import PropTypes from 'prop-types';
MyComponent.propTypes = {
// 你可以将属性声明为 JS 原生类型,默认情况下
// 这些属性都是可选的。
optionalArray: PropTypes.array,
optionalBool: PropTypes.bool,
optionalFunc: PropTypes.func,
optionalNumber: PropTypes.number,
optionalObject: PropTypes.object,
optionalString: PropTypes.string,
optionalSymbol: PropTypes.symbol,
// 任何可被渲染的元素(包括数字、字符串、元素或数组)
// (或 Fragment) 也包含这些类型。
optionalNode: PropTypes.node,
// 一个 React 元素。
optionalElement: PropTypes.element,
// 一个 React 元素类型(即,MyComponent)。
optionalElementType: PropTypes.elementType,
// 你也可以声明 prop 为类的实例,这里使用
// JS 的 instanceof 操作符。
optionalMessage: PropTypes.instanceOf(Message),
// 你可以让你的 prop 只能是特定的值,指定它为
// 枚举类型。
optionalEnum: PropTypes.oneOf(['News', 'Photos']),
// 一个对象可以是几种类型中的任意一个类型
optionalUnion: PropTypes.oneOfType([
PropTypes.string,
PropTypes.number,
PropTypes.instanceOf(Message)
]),
// 可以指定一个数组由某一类型的元素组成
optionalArrayOf: PropTypes.arrayOf(PropTypes.number),
// 可以指定一个对象由某一类型的值组成
optionalObjectOf: PropTypes.objectOf(PropTypes.number),
// 可以指定一个对象由特定的类型值组成
optionalObjectWithShape: PropTypes.shape({
color: PropTypes.string,
fontSize: PropTypes.number
}),
// An object with warnings on extra properties
optionalObjectWithStrictShape: PropTypes.exact({
name: PropTypes.string,
quantity: PropTypes.number
}),
// 你可以在任何 PropTypes 属性后面加上 `isRequired` ,确保
// 这个 prop 没有被提供时,会打印警告信息。
requiredFunc: PropTypes.func.isRequired,
// 任意类型的数据
requiredAny: PropTypes.any.isRequired,
// 你可以指定一个自定义验证器。它在验证失败时应返回一个 Error 对象。
// 请不要使用 `console.warn` 或抛出异常,因为这在 `onOfType` 中不会起作用。
customProp: function(props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error(
'Invalid prop `' + propName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
},
// 你也可以提供一个自定义的 `arrayOf` 或 `objectOf` 验证器。
// 它应该在验证失败时返回一个 Error 对象。
// 验证器将验证数组或对象中的每个值。验证器的前两个参数
// 第一个是数组或对象本身
// 第二个是他们当前的键。
customArrayProp: PropTypes.arrayOf(function(propValue, key, componentName, location, propFullName) {
if (!/matchme/.test(propValue[key])) {
return new Error(
'Invalid prop `' + propFullName + '` supplied to' +
' `' + componentName + '`. Validation failed.'
);
}
})};
React 事件处理
react元素的事件处理和DOM元素类似,有一点语法的不同
- react事件绑定采用驼峰式命名,而不是小写
- 如果采用jsx语法 需要传入一个函数作为事件处理函数,而不是一个字符串(DOM元素写法)
DOM
<button onclick="fn()"></button>
React
<button onClick={ this.fn }></button>
<button onClick={ () => {} }></button>
构造方法改变this – 给组件的实例添加新的方法
直接改变this指向 - 不会给组件实例添加新的方法 (推荐)
传入函数作为事件处理函数 — (推荐)
绑定事件传递参数
传递事件对象参数
传递自定义的参数
React表单
表单元素会保留一些内部状态
- 假设表单组件在子组件中
需要在父组件通过事件句柄,并且作为属性传递到子组件中
封装UI库之-输入框组件
属性 | 描述 | 默认值 | 是否必传 |
---|---|---|---|
type | 类型 | ‘text’ | 否 |
placeholder | 占位符 | ‘’ | 否 |
value | 输入框的值 | ‘’ | 是 |
error | 提示信息 | ‘’ | 否 |
clearable | 清除按钮 | false | 否 |
事件 | 描述 | 默认值 | 是否必传 |
---|---|---|---|
onChange | 输入框值发生变化 | 是 |
react版本TodoList
表单和列表在一个组件
import React from 'react'
class App extends React.Component {
constructor (props) {
super(props)
this.state = {
username: '',
list: []
}
}
changeValue (event) {
let username = this.state.username
username = event.target.value
this.setState({
username
})
}
addlist () {
let list = this.state.list
list.push(this.state.username)
this.setState({
list
})
}
delitem (index) {
let list = this.state.list
list.splice(index, 1)
this.setState({
list
})
}
render () {
return (
<div className="box">
<input type="text" value= { this.state.username } onChange= { this.changeValue.bind(this) }/>
<button onClick={ this.addlist.bind(this) }>添加</button>
<ul>
{ this.state.list.length > 0 ? this.state.list.map((item, index) => {
return <li key={ index}> { item } <button onClick={ this.delitem.bind(this, index)}>删除</button></li>
}) : ( <span>暂无数据</span>)}
</ul>
</div>
)
}
}
export default App
- 表单在父组件,列表在子组件