jsx是什么
function App() {
return (
<div>
你好,世界
</div>
);
}
export default App;
可以看到,jsx是一种基于JavaScript和xml编写的,具有这两种语言优点的一种编写UI的新方式,是js的语法扩展
通过webpack的babel编译jsx,将其转换为虚拟dom和渲染函数,通过js渲染原生dom和页面
jsx的特点
- 具有js的可编程能力
- 具有xml的声明式语法
jsx的常见应用
js表达式基础
在jsx模板中,使用{}来声明表达式,它其中的内容会隐式转换为字符串,显示在页面上
const obj = {
str: '字符串',
num: 1,
fn() {return '方法'}
}
function App() {
return (
// 这里的样式是直接在{}里插入对象
<div style={{color: 'red'}}>
{obj.str} {obj.num} {obj.fn()}
</div>
);
}
export default App;
循环渲染
循环渲染,用于结构相似的元素重复渲染,jsx的循环渲染,就是函数重复返回xml,只能说熟悉的同时又有些陌生
循环时使用key属性提高性能,key属性的值必须在循环中是唯一的,通常使用id
const list = ['Java', 'C', 'Rust']
function App() {
return (
<ul>
{/* 可以看到,表达式中的函数仍可以写xml语句,非常灵活 */}
{ list.map(item => <li key={item}>{item}</li>) }
</ul>
);
}
export default App;
条件渲染
条件渲染用于动态的控制页面元素的显示隐藏
简单条件渲染
仅仅只有一个条件,控制页面元素的显示隐藏状态
const userInfo = {
name: '张三',
age: 12
}
let isEdit = false
let isShow = true
function App() {
return (
<div>
{/* 通过 三元表达式 或 短路与 来控制显示隐藏 */}
{isEdit ? <input /> : <span>{userInfo.name}</span>} <br/>
{isShow && <span>{userInfo.age}</span>}
</div>
);
}
export default App;
复杂条件渲染
其实大家应该都有想法了,就是通过函数的if或者switch做判断,返回不同的xml语句即可
let key = 'b'
const fn = (key) => {
switch(key) {
case 0 :
return <span>key为0</span>
case 1 :
return <span>key为1</span>
default :
return typeof key === 'string' ? <div>key为字符串'{key}'</div> : <p>默认</p>
}
}
function App() {
return (
<div>
{ fn(key) }
</div>
);
}
export default App;
绑定事件
在js中给dom绑定事件,需要先获取dom元素,比较麻烦,如果直接在html标签上以属性的形式来添加事件会方便很多,
而在jsx中,dom实际是通过render函数创建的,它会解析jsx中的xml语句,用于生成dom,那为什么不改造一下渲染函数,使他能实现上面的方便事件绑定功能呢?实际上,jsx已经实现了这个功能
通过添加on + 事件名的属性,即可在html元素上绑定事件,它的值即是需要执行的回调函数
带事件对象的普通事件处理函数
function App() {
// e是事件对象
const fn = (e) => {
console.log('被点击了', e);
}
return (
<div>
<button onClick={fn}>点我</button>
</div>
);
}
export default App;
需要传参的事件处理函数
const name = '张三'
function App() {
const fn = (name) => {
console.log('是' + name);
}
return (
<div>
<button onClick={() => fn(name)}>谁点我?</button>
</div>
);
}
export default App;
需要传参的带事件对象的事件处理函数
const name = '张三'
function App() {
const fn = (e, name) => {
console.log('是' + name, e);
}
return (
<div>
<button onClick={(e) => fn(e, name)}>谁点我?</button>
</div>
);
}
export default App;
动态数据渲染
如果我们需要实现点击按钮,控制一个div的显示和隐藏,大家会怎么写?
我在下面写了一段代码,他能实现我刚刚所需要的功能吗?
const userInfo = {
name: '张三'
}
let isShow = true
function App() {
const fn = () => {
console.log(isShow ? '显示' : '隐藏');
isShow = !isShow
}
return (
<div>
{isShow && <div>{userInfo.name}</div>}
<button onClick={fn}>点击</button>
</div>
);
}
export default App;
很奇怪,我们能看到控制台正确的打印了div的显示隐藏状态,但实际上,他并没有随着数据改变而改变状态
数据的改变,其实并不会动态的影响到页面的展示,这显然有点反逻辑
而react提供了useState这个API来解决这个问题,它返回一个数组,第一个元素是变量的值,第二个元素是一个方法,能够根据参数修改这个值并在页面中渲染,利用解构,我们可以这么写:
const [变量名, 修改变量值并渲染的方法] = useState(初始值)
注意:
- 必须用useState提供的方法修改值,否则无法动态渲染
- 复杂数据类型赋新值的时候,需要创建一个新的引用,也就是说如果你的对象中某个属性变了,你需要新创建一个对象作为set函数的实参
简单数据类型
import { useState } from "react";
const userInfo = {
name: '张三'
}
function App() {
// 使用useState来给xml元素绑定状态(数据)
// 通过解构,声明isShow存储值,声明setIsShow存储修改isShow的值的方法,
// useState的实参,是声明的变量的默认值
const [isShow, setIsShow] = useState(true)
const fn = () => {
setIsShow(!isShow)
console.log(isShow ? '显示' : '隐藏');
}
return (
<div>
{isShow && <div>{userInfo.name}</div>}
<button onClick={fn}>点击</button>
</div>
);
}
export default App;
复杂(引用)数据类型
import { useState } from "react";
function App() {
const [userInfo, setUserInfo] = useState({
name: '张三'
})
const fn = () => {
// 利用解构和它的覆盖,修改属性的值,添加同理,删除的话先删在解构即可
setUserInfo({
...userInfo,
name: '李四'
})
// 或者使用传入函数的方式
// setUserInfo((userInfo) => {
// userInfo.name = '李四'
// return {...userInfo}
// })
}
return (
<div>
<div>{userInfo.name}</div>
<button onClick={fn}>点击将用户名称改为李四</button>
</div>
);
}
export default App;
很好,这下功能实现了...吗?
很喜欢程序员发现bug时的一句话,啊?
如果不是我在这里打印,我还真没发现,聪明的小伙伴估计已经猜到了,这个值的修改,是异步的,我们没法修改之后直接拿过来用!
那么解决方法是什么呢?
很简单,搞一个新变量存一下新值,之后使用这个变量即可,也可以使用useEffect