今天(指两天)继续学习 React。
1. 事件
1.1 JSX 属性写法
//普通 html:
<button onclick="printMe()"></button>
// JSX
<button onClick={printMe()}></button>
可以看到:①onclick成为了onClick。②函数不能用引号
1.2 添加事件
在 React 中,通常是在元素初始化的时候添加监听器,而不是用 addEventListener,因为操作的基本都是 React 元素而不是 DOM 元素。
// function 组件
function Button(props){
function handleClick(e){
e.target.style.color = "red";
}
return (<button onClick={handleClick}>A button</button>);
}
class 组件需要注意 this 的指向,因为在 onClick={handleClick}
中,handleClick 是回调函数,回调函数的 this 是指向 window 的,这是 JS 的默认行为。因此需要在构造函数中对 handleClick 进行绑定处理(这没有问题,因为原型方法比构造函数更早)。
// class 组件
class Button extends React.Component {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this); // 给 handleClick 绑定 this
// 因为该函数之后会被用作回调函数
}
handleClick() {
console.log(this);
}
render() {
return (
<button onClick={ this.handleClick }> // 回调函数
A button
</button>
);
}
}
1.3 给事件添加参数
给事件处理函数添加参数有两种方法,箭头函数或者 bind。
<button onClick={ (e) => this.handleClick(id, e, oid) }>A button</button>
<button onClick={ this.handleClick.bind(this, id, oid) }>A button</button>
区别在于事件对象的传入(皆以上面代码的参数传入顺序为例):
- 第一种方式,e 在传入的时候在什么位置,handleClick 时就在什么位置。
- 第二种方式,e 作为最后一个参数被传入。
2. 条件渲染
条件渲染并不是新的语法,只是一种使用方式。比如说创建三个组件,UserGreeting
, GuestGreeting
, Greeting
。其中 Greeting
根据登录状态返回剩余两个组件中的一个。
2.1 元素变量
把一些元素存进变量,之后再用大括号组合进其他元素,由于变量可以根据条件改变,渲染也会改变,如下图(LoginButton 和 LogoutButton 事先已创建)。
2.2 与运算符 &&
上面在大括号里嵌入存储了元素的变量。其实由于大括号里可以嵌入表达式,还有很多种方式来写。比如与运算符 &&。
return ( { isLogin && <LogoutButton />} );
isLogin 为 false 的时候,后面的部分不会运行。老技巧了。
2.3 三元运算符
没什么好说的。上面的例子可以改写成这样。
简化了许多。
2.4 null 表示不渲染
如果在 render 里返回 null,则组件不会被渲染。
但是组件的生命周期不受影响会照常进行。
3. 列表 & Key
3.1 列表
表达式可以解析列表。
- 普通列表:
- 列表里有元素:
3.2 key
如果运行上述第二个代码,控制台会有报错提示每一个列表元素必须有 key 属性,如下:
- 在控制台上是找不到这个属性的,这是用于辅助 React 来识别元素的修改的,因此每个 key 需要在这个列表中是独一无二的字符串。
- 如果不定义 key,会默认使用元素的索引建立 key,但是不建议这样做,会有很多问题。比如说元素顺序修改了。
3.3 key 定义的地方
key 只有放在数组上下文附近才有意义。这个不好描述,具体见文章。
3.4 key 的使用
key 只能被 React 自身使用,没法访问。如果想要使用 key 的值,只能在传值给 key 的时候,传给一个别的属性,再去访问那个属性。
4. 表单
4.1 受控组件
受控组件指的是受代码控制而不是用户控制的组件。
一个普通的表单元素,会受到用户控制,每当用户输入的时候,表单的 value 就会更改。
要想接受用户的输入,就要使用组件的 state,例如:
- 但是这样的问题在于,这只是做了一次初始化,生成一个输入框,初始值为 state 的初始值。
- 并且此时如果在浏览器中打开会发现,输入框变成只读了,永远显示初始值,不能被更改。
- 这样的结果是可以预测的,因为输入框的值是
this.state.name
,用户输入的时候并不会更改这个值,所以显示的结果也就只会是初始值不变。 - 虽然这不是我们想要的,但是可以看出此时输入框的值已经完全受代码控制而不是用户控制了,因此被称作受控组件。
4.1.1 控制值-input[type="text"]
为了控制填入的值,需要使用 onChange
,每次输入框用户改变值的时候,都会更新 state:
-
e 事件被传入是可以预测的,因为 onChange 是 React 的语法,其背后还是 js 的 onchange 函数,以上写法其实相当于:
const btn = document.querySelector("input[type='input']"); btn.onchange = (e) => {};
事件函数本来就会有 e 传入,很合理。
4.1.2 textarea
原始的 textarea 的值并不是 value 属性而是标签内部内容,但是 React 将其改为 value 属性,因此用法完全和 input 一样。
4.1.3 单选/多选 select
写法如下: 需要注意的几点如下:
- 一旦被受控,selected 就没有意义
- 如果要选多个值,则 value 为数组。
- 直接写 multiple 也行,如果要写 true,就必须加大括号
- handleChange 不能用 e.target.value,这个只有一个值,选择了多个返回的是 selectedOptions。不过这个属性 IE 不支持,如果要支持,参考这里的回答。
4.1.4 文件输入 input[type="file"]
文件输入只能被用户控制,只能为非受控组件。
4.1.5 处理多个输入
这里指的不是 multiple select 那种。而是处理多个输入标签,如:。
处理方式是加上 name 属性,handleChange 的时候根据 name 判断更改哪个框的值。
- 注意 checkbox 的输入值为 e.target.checked。(radio 也是)
4.1.6 value 的可编辑性
一般来说,如果设置了 value 的值,则输入框会变成只读。但有时候设置了 value(并且没有设置 handleChange),但仍然可以编辑,那说明 value 的值为 null 和 undefined。(比如说使用某个变量的值,然后这个变量因为某种情况变成了 undefined 或者 null。)
- value 固定为 11
- value 为 null
4.2 非受控组件
从上面可以看出,每一种输入类型都要为之写专门的输入处理,这很麻烦。有时候只需要简单的输入然后提交,不需要做复杂的判断(比如实时判断),只需要正在提交的时候是正确的值即可。那么此时可以用非受控组件。
由于非受控组件需要使用 ref,放在之后学习。不过有一张表显示两者之间的区别,助你决定使用哪个:
- 上图出处为这篇文章,区别介绍的更加详细。
4.3 成熟的表单提交解决方案
官方文档推荐了 Formik,用于轻松管理复杂的表单验证。
5. 状态提升
状态提升用于多个组件共享相同的变化数据。
这里还是参考文档来看比较好。
一些坑和心得:
- render 中使用 if...else... 判断时,即使 if...else...囊括了所有情况,编译器也不让通过。要用三目运算符
- 状态提升用的还是自上而下的数据流。数据从父组件流向子组件。
- 整个例子的流程就像是:
6. 组合
6.1 props.children
props.children
是一个特殊命名的属性:
这里使用组件的方式不再是 <Panel />
,而是使用开放和闭合标签包裹了一段 html 内容。这段内容将会作为 props.children
传给子组件。
6.2 传递自定义元素
props.children
是特殊属性,传的是整个 innerHTML。如果想传一些自定义的元素的话。可以直接以类似:<MyComponent myDefined={<h1>this is a title</h1>}>
的方式传递,props 并不对值的类型有要求。JSX 语法本身也只是元素。
6.3 组合
可以通过以上语法 “组合” 成新的组件。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!