七、组件实例三大属性之props
1、props基本使用
在官方文档中讲组件,从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。所以可以理解props为组件中存储信息的部分,类似于函数的参数。
<body>
<div id="test1"></div>
<div id="test2"></div>
<div id="test3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">
class Person extends React.Component{
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="jerry" age={19} sex="男"/>,document.getElementById('test1'))
ReactDOM.render(<Person name="tom" age={18} sex="女"/>,document.getElementById('test2'))
const p = {name:'老刘',age:18,sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))
</script>
</body>
先引入相关的库,然后准备好三个测试用例。创建一个类型组件,初始化这个组件的propsconst {name,age,sex} = this.props 利用es6的解构赋值来初始化。使用const是因为props是只读的,不能修改其中的值。渲染的时候将信息携带到对应组件上,使每个组件显示的内容不同。前两个例子都是单独携带数据,字符串用双引号,number用单括号。第三个例子用es6的解构赋值一次性把所有信息携带过去,最终在页面上显示出来。
2、对props进行限制
传入数据的时候可能因为数据类型的错误导致页面报错或者无法显示,所以需要对传入的props的数据类型进行一定的限制。
<script type="text/babel">
class Person extends React.Component{
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
Person.propTypes = {
name:PropTypes.string.isRequired,
sex:PropTypes.string,
age:PropTypes.number,
speak:PropTypes.func,
}
Person.defaultProps = {
sex:'男',
age:18
}
ReactDOM.render(<Person name={100} speak={speak}/>,document.getElementById('test1'))
ReactDOM.render(<Person name="tom" age={18} sex="女"/>,document.getElementById('test2'))
const p = {name:'老刘',age:18,sex:'女'}
ReactDOM.render(<Person {...p}/>,document.getElementById('test3'))
</script>
这里是引入了核心库,一次性把需要的东西都引入了进来,所以propTypes和defaultProps可以直接使用,之后创建脚手架后需要在对应组件引入相对于的库,这里需要注意一下,否则现在写着有效果,脚手架项目中没有效果了。
3、props的简写方式
利用类的构造器对props进行简写。
<script type="text/babel">
class Person extends React.Component{
constructor(props){
super(props)
}
render(){
const {name,age,sex} = this.props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age+1}</li>
</ul>
)
}
}
ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1'))
</script>
4、函数组件使用props
之前说props和组件的关系类似于参数和函数的关系,所以函数式组件中props是被当做参数传入组件中的。其他使用都和类式组件类似。
<script type="text/babel">
function Person (props){
const {name,age,sex} = props
return (
<ul>
<li>姓名:{name}</li>
<li>性别:{sex}</li>
<li>年龄:{age}</li>
</ul>
)
}
ReactDOM.render(<Person name="jerry"/>,document.getElementById('test1'))
</script>
八、组件实例三大属性之refs
首先要了解啥是refs啊,官方的定义为:React 支持一个特殊的、可以附加到任何组件上的 ref 属性。此属性可以是一个由 React.createRef() 函数创建的对象、或者一个回调函数、或者一个字符串(遗留 API)。当 ref 属性是一个回调函数时,此函数会(根据元素的类型)接收底层 DOM 元素或 class 实例作为其参数。这能够让你直接访问 DOM 元素或组件实例。
1、字符串形式的ref
<script type="text/babel">
class Demo extends React.Component{
showData = ()=>{
const {input1} = this.refs
alert(input1.value)
}
showData2 = ()=>{
const {input2} = this.refs
alert(input2.value)
}
render(){
return(
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>
标签中绑定的是ref,我们要获取的是refs,是很多个ref在一起的结果。
2、回调函数形式的ref
<script type="text/babel">
class Demo extends React.Component{
showData = ()=>{
const {input1} = this
alert(input1.value)
}
showData2 = ()=>{
const {input2} = this
alert(input2.value)
}
render(){
return(
<div>
<input ref={c => this.input1 = c } type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData2} ref={c => this.input2 = c } type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>
其实函数回调写法和第一种写法差别不大,一个把回调写到函数里,一个把回调写到标签中。
3、createRef的使用
<script type="text/babel">
class Demo extends React.Component{
myRef = React.createRef()
myRef2 = React.createRef()
showData = ()=>{
alert(this.myRef.current.value);
}
showData2 = ()=>{
alert(this.myRef2.current.value);
}
render(){
return(
<div>
<input ref={this.myRef} type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData2} ref={this.myRef2} type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点,该容器是“专人专用”的,具体使用方法如上所示。
九、react中的事件处理
- 通过onXxx属性指定事件处理函数(注意大小写)
a.React使用的是自定义(合成)事件, 而不是使用的原生DOM事件为了更好的兼容性 b.React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)为了的高效 - 通过event.target得到发生事件的DOM元素对象不要过度使用ref
十、react中收集表单数据
在 HTML 中,表单元素(如<input>、 <textarea> 和 <select> )通常自己维护 state,并根据用户输入进行更新。而在 React 中,可变状态通常保存在组件的 state 属性中,并且只能通过使用 setState()来更新。 我们可以把两者结合起来,使 React 的 state 成为“唯一数据源”。渲染表单的 React 组件还控制着用户输入过程中表单发生的操作。被 React 以这种方式控制取值的表单输入元素就叫做“受控组件”。
非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。
1、非受控组件
<script type="text/babel">
class Login extends React.Component{
handleSubmit = (event)=>{
event.preventDefault()
const {username,password} = this
alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
}
render(){
return(
<form onSubmit={this.handleSubmit}>
用户名:<input ref={c => this.username = c} type="text" name="username"/>
密码:<input ref={c => this.password = c} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('test'))
</script>
2、受控组件
<script type="text/babel">
class Login extends React.Component{
state = {
username:'',
password:''
}
saveUsername = (event)=>{
this.setState({username:event.target.value})
}
savePassword = (event)=>{
this.setState({password:event.target.value})
}
handleSubmit = (event)=>{
event.preventDefault()
const {username,password} = this.state
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}
render(){
return(
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveUsername} type="text" name="username"/>
密码:<input onChange={this.savePassword} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
ReactDOM.render(<Login/>,document.getElementById('test'))
</script>
十一、高阶函数_函数柯里化
1、高阶函数
如果一个函数符合下面两个个规范中的任何一个,那该函数就是高阶函数。
- 若A函数,接收的参数是一个函数,那么A就可以称之为高阶函数。
- 若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数。
常见的高阶函数有:Promise、setTimeout、arr.map()等等
2、函数的柯里化
通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式。
function sum(a){
return(b)=>{
return (c)=>{
return a+b+c
}
}
}
|