require-v-for-key.js 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /**
  2. * @author Toru Nagashima
  3. * @copyright 2017 Toru Nagashima. All rights reserved.
  4. * See LICENSE file in root directory for full license.
  5. */
  6. 'use strict'
  7. // ------------------------------------------------------------------------------
  8. // Requirements
  9. // ------------------------------------------------------------------------------
  10. const utils = require('../utils')
  11. // ------------------------------------------------------------------------------
  12. // Rule Definition
  13. // ------------------------------------------------------------------------------
  14. module.exports = {
  15. meta: {
  16. type: 'problem',
  17. docs: {
  18. description: 'require `v-bind:key` with `v-for` directives',
  19. category: 'essential',
  20. url: 'https://eslint.vuejs.org/rules/require-v-for-key.html'
  21. },
  22. fixable: null,
  23. schema: []
  24. },
  25. create (context) {
  26. /**
  27. * Check the given element about `v-bind:key` attributes.
  28. * @param {ASTNode} element The element node to check.
  29. */
  30. function checkKey (element) {
  31. if (element.name === 'template' || element.name === 'slot') {
  32. for (const child of element.children) {
  33. if (child.type === 'VElement') {
  34. checkKey(child)
  35. }
  36. }
  37. } else if (!utils.isCustomComponent(element) && !utils.hasDirective(element, 'bind', 'key')) {
  38. context.report({
  39. node: element.startTag,
  40. loc: element.startTag.loc,
  41. message: "Elements in iteration expect to have 'v-bind:key' directives."
  42. })
  43. }
  44. }
  45. return utils.defineTemplateBodyVisitor(context, {
  46. "VAttribute[directive=true][key.name='for']" (node) {
  47. checkKey(node.parent.parent)
  48. }
  49. })
  50. }
  51. }