但是在上面的代码,你会得到一个报错:提醒你当循环一个数组时应该提供 keys。Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 Nerv/小程序 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。
const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]const listItems = numbers.map((number) => {return <Textkey={String(number)}className='li'>我是第 {number + 1} 个数字</Text>})
taroKeys
taroKey 适用于循环渲染原生小程序组件,赋予每个元素唯一确定标识,转换为小程序的 wx:key。
const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]const listItems = numbers.map((number) => {return (// native component<g-listtaroKey={String(number)}className='g-list'>我是第 {number + 1} 个数字</g-list>)})
元素的 key 在他的兄弟元素之间应该唯一
数组元素中使用的 key 在其兄弟之间应该是独一无二的。然而,它们不需要是全局唯一的。当我们生成两个不同的数组时,我们可以使用相同的 key:
class App extends Componenet {state = {posts: [{id: 1, title: 'Hello World', content: 'Welcome to learning Taro!'},{id: 2, title: 'Installation', content: 'You can install Taro from npm.'}]}render () {const { posts } = this.stateconst sidebar = (<View>{posts.map((post) =><Text key={post.id}>{post.title}</Text>)}</View>)const content = posts.map((post) => {return <View key={post.id}><Text>{post.title}</Text><Text>{post.content}</Text></View>})return (<View>{sidebar}<View className="divider" />{content}</View>)}}
key 会作为给 Taro 的提示,但不会传递给你的组件。如果您的组件中需要使用和 key 相同的值,请将其作为属性传递:
const content = posts.map((post) => {return <View key={post.id} id={post.id} ><Text>{post.title}</Text><Text>{post.content}</Text></View>})
key 的取值
key 的取值必须同时满足三个条件:
- 稳定
- 可预测
- 唯一(相对于其他兄弟元素)
最好的 key 就是数组里的 ID(通常由后端生成),他能同时满足以上三个条件,同时也不需要自己去生成。如果没有 ID,你能保证数组的元素某个键值字符串都是不同的(例如 item.title),那么使用那个字符串键值也可以。如果源数据没有提供很好的 key 值,或者需要遍历的数组生成的。那么你最好在数据创建或者修改之后给他添加一个好的 key 值:
let todoCounter = 0function createNewTodo(text) {return {completed: false,id: todoCounter++,text}}class App extends Components {state = {todos: [],inputText: ''}onNewTodo () {this.setState({todos: [...this.state.todos, createNewTodo(this.state.inputText)]})}render () {return ...}}
每一个在渲染结果上一致组件的应该对应一个相同的 key。因此使用数组的 index 或在数组渲染时随机生成一个 key 值(但你在创建数组时可以这么做)都是反优化,极端情况下甚至可能导致渲染出错。
