React节点属性,列表渲染

节点属性渲染

需要注意jsx语法的元素属性

  • 由于jsx语法是和js语法相包容的,所以,jsx里的语法会和js的语法相冲突,比如说,元素的属性值class和js里的关键字class重名,所以,html的元素在jsx的语法里,使用这些属性名的时候就要注意与js的关键字等冲突,这里的class被替换成了className:
<script type="text/babel">
    const element = (
        <div>
            <h2 class="active">Hello word!</h2>
        </div>
    );
    ReactDOM.render(
        element,
        document.querySelector("#app")
    )
</script>

在这里插入图片描述

即便是因为某些原因使其生效了,但是并不符合规范!!!

  • 除此之外,还有很多基本的元素也需要注意:

<script type="text/babel">
    const element = (
        <div>
            <h2 className="active"> Hello word!</h2>
            <input type="button" value="按钮">
            <input type="checkbox" name="ipt" id="ipt" checked/>
        </div>
    );
    ReactDOM.render(
        element,
        document.querySelector("#app")
    )
</script>

在这里插入图片描述

  • 也比如label的for:

<script type="text/babel">
    const element = (
        <div>
            <h2 className="active">Hello word!</h2>
            <label for="ipt">单选按钮</label>
            <input type="checkbox" name="ipt" id="ipt" defaultChecked />
        </div>
    );
    ReactDOM.render(
        element,
        document.querySelector("#app")
    )
</script>

在这里插入图片描述

jsx的语法相对html是较严格的,标签必须规范,自闭和标签必须闭合等。

react的语法提示也是非常亲民,不用过于担心。

列表渲染

  • 如果是数组,自动根据key值遍历:
<script type="text/babel">
    const arr = [
        1,
        2,
        3
    ]
    const arr2 = [
        'a',
        'b',
        'c'
    ]
    const arrLi = [
        <li key="1">1</li>,
        <li key="2">2</li>,
        <li key="3">3</li>
    ]
    const element = (
        <div>
            {arrLi}
            {arr}
            {arr2}
        </div>
    );
    ReactDOM.render(element,document.querySelector("#app"))
</script>

当然,这些无效的数组可以通过map方法重新打包成<li>{number}</li>的jsx对象,然后返回给渲染的元素。

在这里插入图片描述

  • 如果是对象:

<script type="text/babel">
     const obj = [
         {
             name:'Bob',
             age:'18',
             sex:'女'
         },
         {
             name:'Lucy',
             age:'16',
             sex:'女'
         },
         {
             name:'Atom',
             age:'80',
             sex:'男'
         }
     ]
     const element = []
     obj.forEach((item,index)=>{
         element.push(<li key={index}>name:{item.name} - age:{item.age} - sex:{item.sex}</li>);
         //如果渲染的是数组,一定要在每一个渲染对象里插入key,作为遍历参考!不然会报错
     })
     ReactDOM.render(element,document.querySelector("#app"))
 </script>

在这里插入图片描述

为什么渲染列表需要键入key值

  • Keys可以在DOM中的某些元素被增加或删除的时候帮助React识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
  • 一个元素的key最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据的id作为元素的key:
const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);
  • 元素的key只有在它和它的兄弟节点对比时才有意义。

比方说,如果你提取出一个ListItem组件,你应该把key保存在数组中的这个<ListItem />元素上,而不是放在ListItem组件中的<li>元素上。

  • 如果使用组件化思想,你定义了一个list的组件,用于列表的渲染:
function ListItem(props) {
	const value = props.value;
	return (
		// 错啦!你不需要在这里指定key:
		<li key={value.toString()}>
		  {value}
		</li>
	);
}

function NumberList(props) {
	const numbers = props.numbers;
	const listItems = numbers.map((number) =>
	  //错啦!元素的key应该在这里指定:
	  <ListItem value={number} />
	);
	return (
	  <ul>
	    {listItems}
	  </ul>
	);
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
	<NumberList numbers={numbers} />,
	document.getElementById('root')
);

  • 正确的使用方式
<script type="text/babel">
    function ListItem(props) {
        // 对啦!这里不需要指定key:
        return <li>{props.value}</li>;
    }

    function NumberList(props) {
        const numbers = props.numbers;
        const listItems = numbers.map((number) =>
            //key应该在数组的上下文中被指定
            <ListItem key={number.toString()} value={number} />
        );
        console.log(listItems);
        
        return (
            <ul>
                {listItems}
            </ul>
        );
    }

    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
        <NumberList numbers={numbers} />,
        document.getElementById('app')
    );
</script>

  • 因为本来渲染的时候这个key是用来和兄弟节点做对比,不会显示到html页面中作为一个key的属性,所以,key加载li里是不合适的,也会让react进行不必要的识别,造成拖累性能,加在数组上下文中则会更加方便react渲染和识别。

在这里插入图片描述

  • 不管任何时候,key值应该都是保持唯一性的。

虽然上面用到了组件,但是组件本不难,看一下就知道怎么做了,后面再出详细的笔记。

<think>好的,用户想了解React列表渲染的工作原理以及key属性的作用。我需要从React渲染机制讲起,然后解释列表渲染时的问题,再引入key的作用。记得要结合虚拟DOM和diff算法来说明,同时引用提供的资料中的相关内容。 首先,React渲染过程涉及创建元素树和协调机制。当状态变化时,React会生成新的虚拟DOM树,并与旧的进行比较,这个过程叫做协调(Reconciliation)。列表渲染时,如果没有key,React可能无法正确识别元素,导致性能问题或错误。 接下来,要解释key的作用。key帮助React识别哪些元素改变了,比如被添加或移除。这样在对比新旧虚拟DOM时,React可以更高效地更新,而不是重新渲染整个列表。需要举例说明,比如列表项的顺序变化时,使用key可以避免不必要的重新渲染。 还要提到没有正确使用key的后果,比如使用索引可能导致的问题。同时,引用资料中的React.memo和useCallback,说明在列表渲染中结合这些优化手段可以提升性能。 最后,确保回答结构清晰,分点说明,并附上相关问题。引用提供的参考文献,比如引用[1]关于元素树的创建,引用[2]和[3]关于优化手段和memo的使用。注意使用正确的LaTeX格式,行内公式用$...$,独立公式用$$...$$,不过这里可能不需要数学公式,但如果有需要的地方要正确应用。 可能还需要检查是否有遗漏的关键点,比如diff算法的具体比较过程,或者虚拟DOM的结构如何影响列表更新。确保所有技术术语解释清楚,让不同层次的读者都能理解。</think>### React列表渲染与key属性作用解析 #### 一、列表渲染核心机制 1. **虚拟DOM对比原理** React通过虚拟DOM树的对比(Diffing算法)实现高效更新。当渲染列表时,每个列表项会被转化为React元素对象,例如: ```jsx <ul> {items.map(item => <li>{item.text}</li>)} </ul> ``` 此时若缺少key属性React会默认使用数组索引作为标识[^1]。 2. **Diff算法优化规则** React采用同级比对策略,通过以下步骤优化列表更新: - 识别元素类型变化 - 匹配相同key的元素 - 仅更新变化的属性/状态 #### 二、key属性的核心作用 1. **元素身份标识** 使用唯一且稳定的key值(如ID): ```jsx items.map(item => <ListItem key={item.id} />) ``` 可使React准确追踪元素的移动、添加和删除,避免以下问题: - 错误复用DOM节点导致状态混乱 - 不必要的子组件重新渲染 - 动画/焦点丢失等副作用 2. **性能优化原理** 当列表顺序变化时: ```jsx // 没有key:所有<li>都会被卸载重建 // 正确key:仅DOM节点移动,组件实例复用 ``` 使用key后Diff算法的时间复杂度从$O(n^3)$优化到$O(n)$[^2]。 #### 三、最佳实践与常见误区 1. **正确使用规范** - ✅ 使用数据唯一标识(如数据库ID) - ✅ 组合多个字段生成稳定key - ❌ 避免使用数组索引(动态列表) - ❌ 禁止随机数(导致频繁重建) 2. **与性能优化结合** 结合`React.memo`和`useCallback`实现完整优化链: ```jsx const MemoizedItem = React.memo(ListItem); function List() { const renderItem = useCallback(item => <MemoizedItem {...item} />, []); return items.map(item => <div key={item.id}>{renderItem(item)}</div>); } ``` 这种组合可避免父组件更新引发的子组件不必要渲染[^3]。 $$ \text{优化效果公式:} \\ T_{\text{更新}} = O(n) + \sum_{i=1}^{k} C_{\text{组件i}}} $$ ($k$为实际变化的组件数量) #### 四、调试验证方法 1. 通过React DevTools观察组件渲染次数 2. 添加`console.log`验证组件生命周期 3. 使用严格模式检测异常行为
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔跑的飞牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值