但是在上面的代码,你会得到一个报错:提醒你当循环一个数组时应该提供 keys。Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 Nerv/小程序 识别哪些元素发生了变化。因此你应当给数组中的每一个元素赋予一个确定的标识。

  1. const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]
  2. const listItems = numbers.map((number) => {
  3. return <Text
  4. key={String(number)}
  5. className='li'
  6. >
  7. 我是第 {number + 1} 个数字
  8. </Text>
  9. })

taroKeys

taroKey 适用于循环渲染原生小程序组件,赋予每个元素唯一确定标识,转换为小程序的 wx:key

  1. const numbers = [...Array(100).keys()] // [0, 1, 2, ..., 98, 99]
  2. const listItems = numbers.map((number) => {
  3. return (
  4. // native component
  5. <g-list
  6. taroKey={String(number)}
  7. className='g-list'
  8. >
  9. 我是第 {number + 1} 个数字
  10. </g-list>
  11. )
  12. })

元素的 key 在他的兄弟元素之间应该唯一

数组元素中使用的 key 在其兄弟之间应该是独一无二的。然而,它们不需要是全局唯一的。当我们生成两个不同的数组时,我们可以使用相同的 key:

  1. class App extends Componenet {
  2. state = {
  3. posts: [
  4. {id: 1, title: 'Hello World', content: 'Welcome to learning Taro!'},
  5. {id: 2, title: 'Installation', content: 'You can install Taro from npm.'}
  6. ]
  7. }
  8. render () {
  9. const { posts } = this.state
  10. const sidebar = (
  11. <View>
  12. {posts.map((post) =>
  13. <Text key={post.id}>
  14. {post.title}
  15. </Text>
  16. )}
  17. </View>
  18. )
  19. const content = posts.map((post) => {
  20. return <View key={post.id}>
  21. <Text>{post.title}</Text>
  22. <Text>{post.content}</Text>
  23. </View>
  24. })
  25. return (
  26. <View>
  27. {sidebar}
  28. <View className="divider" />
  29. {content}
  30. </View>
  31. )
  32. }
  33. }

key 会作为给 Taro 的提示,但不会传递给你的组件。如果您的组件中需要使用和 key 相同的值,请将其作为属性传递:

  1. const content = posts.map((post) => {
  2. return <View key={post.id} id={post.id} >
  3. <Text>{post.title}</Text>
  4. <Text>{post.content}</Text>
  5. </View>
  6. })

key 的取值

key 的取值必须同时满足三个条件:

  1. 稳定
  2. 可预测
  3. 唯一(相对于其他兄弟元素)

最好的 key 就是数组里的 ID(通常由后端生成),他能同时满足以上三个条件,同时也不需要自己去生成。如果没有 ID,你能保证数组的元素某个键值字符串都是不同的(例如 item.title),那么使用那个字符串键值也可以。如果源数据没有提供很好的 key 值,或者需要遍历的数组生成的。那么你最好在数据创建或者修改之后给他添加一个好的 key 值:

  1. let todoCounter = 0
  2. function createNewTodo(text) {
  3. return {
  4. completed: false,
  5. id: todoCounter++,
  6. text
  7. }
  8. }
  9. class App extends Components {
  10. state = {
  11. todos: [],
  12. inputText: ''
  13. }
  14. onNewTodo () {
  15. this.setState({
  16. todos: [...this.state.todos, createNewTodo(this.state.inputText)]
  17. })
  18. }
  19. render () {
  20. return ...
  21. }
  22. }

每一个在渲染结果上一致组件的应该对应一个相同的 key。因此使用数组的 index 或在数组渲染时随机生成一个 key 值(但你在创建数组时可以这么做)都是反优化,极端情况下甚至可能导致渲染出错。