React中文文档之Lists and Keys

Lists and Keys
首先,让我们回顾一下,在js中如何变换列表。
下面给出的代码,我们使用 'map()' 函数作用一个 'numbers' 数组,并且使数组中的元素值*2.我们分配由 'map()' 返回的新数组给变量 'doubled',并且在console中输出:
		const numbers = [1, 2, 3, 4, 5];
		const doubled = number.map((numer) => number * 2);
		console.log(doubled);
这段代码在console中输出:[2, 4, 6, 8, 10]
在React中,变换数组为元素列表,同js中差不多是一样的。


渲染多个组件
你可以构建元素集合,并且通过使用 '{}',在JSX中来引入它们。
下面,我们通过js的 'map()' 函数来循环 'numbers' 数组。对数组的每个条目,返回一个 '<li>' 元素。最终,我们分配元素结果数组给 'listItems':
		const numbers = [1, 2, 3, 4, 5];
		const listItems = numbers.map((number) => 
			<li>{number}</li>
		);
我们在一个 '<ul>' 元素内包含整个 'listItems' 数组,并且渲染为DOM:
		ReactDOM.render(
			<ul>{listItems}</ul>,
			document.getElementById('root')
		);
这段代码展示了一个1-5数字的无序列表


基础列表组件
通常我们希望在一个组件内部渲染列表.
我们重构值钱的例子为一个组件,接收一个 'numbers' 的数组,并且输出一个元素无序列表:
		function NumberList(props) {
			const numbers = props.numbers;
			const listItems = numbers.map((number) =>
				<li>{number}</li>
			);
			return (
				<ul>{listItems}</ul>
			);
		}
		const numbers = [1, 2, 3, 4, 5];
		ReactDOM.render(
			<NumberList numbers={numbers} />,
			document.getElementById('root')	
		);
当你运行这段代码,将给出一个警告,列表条目的key应该被提供。一个 'key' 是一个特殊的字符串属性,当创建元素列表时需要引入。在下个小结,我们将讨论为什么它很重要。
让我们分配一个 'key' 给我们的列表条目,在 'numbers.map()' 内部,并且修复这个丢失的key的问题。
		function NumberList(props) {
			const numbers = props.numbers;
			const listItems = numbers.map((number) =>
				<li key={number.toString()}>		// 这里新增了key属性
					{number}
				</li>
			);
			return (
				<ul>{listItems}</ul>
			);
		}
		const numbers = [1, 2, 3, 4, 5];
		ReactDOM.render(
			<NumberList numbers={numbers} />,
			document.getElementById('root')	
		);

keys
keys帮助React识别列表中哪个条目修改过、新增的或者被移除。数组内的元素应该给出keys属性,以赋予元素一个稳定的标识:
		const numbers = [1, 2, 3, 4, 5];
		const listItems = numbers.map((number) => 
			<li key={number.toString()}>
				{number}
			</li>
		);
选择key的最佳方法是使用一个字符串,来唯一标识列表项的每一个元素。大多数情况下,你会使用数据的IDs作为keys:
		const todoItems = todos.map((todo) =>
			<li key={todo.id}>
				{todo.text}
			</li>
		);

当要渲染的条目没有稳定的IDs,你可以使用列表条目的索引作为key,作为最后一种选择:
		const todoItems = todos.map((todo, index) =>

			// Only do this if items have no stable IDs
			<li key={index}>
				{todo.text}
			</li>
		);

如果列表条目可能被重排,我们不建议使用条目索引作为key,因为这样会很慢(React计算条目哪些被修过、是新增的,还是移除了哪些条目,比较缓慢)。如果你感兴趣,可以阅读 'in-depth explanation about why keys are necessary' 这节。


使用keys来提取组件
keys只有在数组的上下文中才有意义。
例如:如果你提取一个 'ListItem' 组件,你应该保证 <ListItem> 元素上的key在这个数组中,而不是在根 <li> 元素在 'ListItem' 自身上。

不正确的key的使用:
		function ListItem(props) {
			const value = props.vaue;
			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>
					{listItem}
				</ul>
			);
		}

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

正确的key的使用:
		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} />
			);
			return (
				<ul>
					{listItem}
				</ul>
			);
		}

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

一个好的经验法则是:在 'map()' 调用的内部元素需要key。


在兄弟元素间,必须保证key是唯一的
数组内部使用的key,在它的兄弟元素之间必须是唯一的。但是它们没必要是全局唯一。不同数组间,是可以使用相同的key的:
		function Blog(props) {
			const sidebar = (
				<ul>
					{props.posts.map((post) =>
						<li key={post.id}>
							{post.title}
						</li>
					)}
				</ul>
			);
			const content = props.posts.map((post) =>
				<div key={post.id}>
					<h3>{post.title}</h3>
					<p>{post.content}</p>
				</div>
			);
			return (
				<div>
					{sidebar}
					<hr />
					{content}
				</div>
			);
		}
		const posts = [
			{id: 1, title: 'Hello World', content: 'Welcome to learning React!'},
			{id: 2, title: 'Installation', content: 'You can install React from npm.'}
		];
		ReactDOM.render(
			<Blog posts={posts} />,
			document.getElementById('root')
		);

keys作为一个提示服务于React,但它们并不传递给你的组件。如果在你的组件中需要同样的值,将 key 作为一个 prop(使用不同的名字) 来明确地传递它:
		const content = post.map((post) => 
			<Post 
				key={post.id} 	// key只是React用于检测列表条目的变化(不会供我们内部props使用)
				id={post.id} 	// 我们再定义一个id,内部就可以通过 props.id 来使用了
				title={post.title}>	
		);

上面的示例,'Post' 组件可以读取 'props.id',而不能读取 'props.key'


在JSX中嵌入 'map()'
在之前的例子中,我们声明了一个独立的 'listItems' 变量,并在 JSX 中包含:
		function NumberList(props) {
			const numbers = props.numbers;
			const listItems = numbers.map((number) =>
				<ListItem key={number.toString()} value={number} />
			);
			return (
				<ul>
					{listItem}
				</ul>
			);
		}

JSX允许在 '{}' 内嵌入任意表达式,因此我们可以内联 'map()' 的结果:
		function NumberList(props) {
			const numbers = props.numbers;
			const listItems = numbers.map((number) =>
				<ListItem key={number.toString()} value={number} />
			);
			return (
				<ul>
					{numbers.map((number) =>
						<ListItem key={number.toString()} value={number} />
					)}
				</ul>
			);
		}

有时候,这样更清晰明了,但是这种方式有可能被滥用。就像在js中,它取决于你,来决定为了可读性,是否值得提取一个变量。牢记:如果 'map()' 体也是嵌套的,这可能是一个提取组件的好时机。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值