Vue组件使用入门实例及常见错误解决

以你之姓@ 2021-11-17 12:42 564阅读 0赞

定义Vue组件名的方式有两种:

使用 kebab-case

  1. Vue.component('my-component-name', { /* ... */ })

当使用 kebab-case (短横线分隔命名) 定义一个组件时,必须在引用这个自定义元素时使用 kebab-case,例如 <my-component-name>

使用 PascalCase

  1. Vue.component('MyComponentName', { /* ... */ })

当使用 PascalCase (首字母大写命名) 定义一个组件时,在引用这个自定义元素时两种命名法都可以使用。
也就是说 <my-component-name><MyComponentName> 都是合法的。
注意,尽管如此,直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case 是有效的。

Prop 的大小写 (camelCase 和 kebab-case)

HTML 中的特性名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。
这意味着当使用 DOM 中的模板时,camelCase (驼峰命名法) 的 prop 名需要使用其等价的 kebab-case (短横线分隔命名) 命名:

  1. Vue.component('blog-post', {
  2. // 在 JavaScript 中是 camelCase 的
  3. props: ['postTitle'],
  4. template: '<h3>{
  5. { postTitle }}</h3>'
  6. })

在HTML 中,需要将组件的属性 postTitle 改成 post-title。

  1. <!-- 在 HTML 中是 kebab-case 的 -->
  2. <blog-post post-title="hello!"></blog-post>

重申一次,如果使用字符串模板,那么这个限制就不存在了。
即直接可以在 template 字符串中使用 postTitle 属性.

  1. Vue.component('blog-post3', {
  2. props: ['postTitle'],
  3. template: `
  4. <div class="blog-post">
  5. <p> {
  6. { postTitle }}</p>
  7. </div>
  8. `
  9. })

错误1: component lists rendered with v-for should have explicit keys.

  1. // cosole警告提示:
  2. vue.js:640 [Vue tip]: <blog-post-list2 v-for="postdetail in postList">:
  3. component lists rendered with v-for should have explicit keys.
  4. See https://vuejs.org/guide/list.html#key for more info.
  5. (found in <Root>)

错误原因: 没有为循环的每一个项提供唯一 key 属性

解决办法: 需要为 每项提供一个唯一 key 属性,找个key可以使用字符串数值类型的值。

这里是Vue文档中给他说明:

  1. 为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性:
  2. <div v-for="item in items" v-bind:key="item.id">
  3. <!-- 内容 -->
  4. </div>
  5. 建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
  6. 因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联
  7. 不要使用对象或数组之类的非基本类型值作为 v-for key。请用字符串或数值类型的值。

错误2:[Vue warn]Duplicate keys detected: 1. This may cause an update error.

  1. // cosole报错:
  2. [Vue warn]: Duplicate keys detected: '1'. This may cause an update error.
  3. (found in <Root>)

错误原因: 因为在测试中,使用的同一个数据,因此再多个列表中,属性key存在重复。

解决办法: 修改每个循环中的key,给key值加个前缀,让其不要重复即可。

  1. 列表1:
  2. <blog-post-list
  3. v-for="postdetail in postList"
  4. v-bind:key="'list1-' + postdetail.id"
  5. v-bind:postdetail="postdetail"
  6. ></blog-post-list>
  7. 列表2
  8. <blog-post-list2
  9. v-for="post2 in postList"
  10. v-bind:key="'list2-' + post2.id"
  11. v-bind:post2="post2"
  12. ></blog-post-list2>

错误3: camelCased props need to use their kebab-case equivalents when using in-DOM templates

  1. [Vue tip]: Prop "postdetail" is passed to component <Anonymous>, but the declared prop name is "postDetail".
  2. Note that HTML attributes are case-insensitive
  3. and camelCased props need to use their kebab-case equivalents when using in-DOM templates.
  4. You should probably use "post-detail" instead of "postDetail".

错误原因: 直接在 DOM (即非字符串的模板) 中使用时只有 kebab-case (短横线分隔命名) 是有效的

解决办法: 修改

  1. <!-- 有效的 -->
  2. <blog-post3
  3. v-for="post3 in postList"
  4. v-bind:key="'list3-' + post3.id"
  5. v-bind:post-detail="post3"
  6. ></blog-post3>
  7. <!-- 无效的,postDetail 必须使用短横线分隔命名,即改成 post-detail即可 -->
  8. <blog-post3
  9. v-for="post3 in postList"
  10. v-bind:key="'list3-' + post3.id"
  11. v-bind:postDetail="post3"
  12. ></blog-post3>

完整的代码实例如下:

  1. <!doctype html>
  2. <html>
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width,height=device-height">
  6. <title>Vue组件</title>
  7. <!-- 引入vue文件 -->
  8. <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
  9. <!-- 引入element样式 -->
  10. <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  11. <!-- 引入element组件库 -->
  12. <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  13. </head>
  14. <body>
  15. <div id="app">
  16. <hr/>
  17. <!-- 通过 Prop 向子组件传递数据 -->
  18. <!-- 一个 prop 被注册之后,在调用组件模板是,可以将数据作为一个自定义的属性传递进来 -->
  19. <strong>使用组件1: 直接在模板属性中传入数据</strong>
  20. <blog-post title="My journey with Vue1" author="作者1"></blog-post>
  21. <blog-post title="My journey with Vue2" author="作者2"></blog-post>
  22. <blog-post title="My journey with Vue3" author="作者3"></blog-post>
  23. <hr/>
  24. <!-- 使用 v-bind 绑定数据,一个属性绑定一次(比较繁琐,不推荐) -->
  25. <strong>使用组件1: 使用 v-bind 绑定数据</strong>
  26. <blog-post
  27. v-for="post in postList"
  28. v-bind:key="post.id"
  29. v-bind:title="post.title"
  30. v-bind:author="post.author"
  31. ></blog-post>
  32. <hr/>
  33. <!-- 使用 v-bind 绑定数据,直接绑定一个对象(减少绑定属性次数,推荐) -->
  34. <!-- 同时,注意该属性绑定的key,增加了前缀,防止在循序数据是时报key值重复问题 -->
  35. <strong>使用组件2: 绑定一个对象</strong>
  36. <blog-post2
  37. v-for="post2 in postList"
  38. v-bind:key="'list2-' + post2.id"
  39. v-bind:post2="post2"
  40. ></blog-post2>
  41. <hr/>
  42. <!-- 使用 v-bind 绑定数据,直接绑定一个对象(减少绑定属性次数,推荐) -->
  43. <!-- 同时,注意该属性绑定的key,增加了前缀,防止在循序数据是时报key值重复问题 -->
  44. <!-- 注意直接在 DOM (即非字符串的模板) 中只能使用 kebab-case (短横线分隔命名) 格式 -->
  45. <strong>使用组件3: 绑定一个对象, DOM 中使用必须使用 kebab-case 格式 </strong>
  46. <blog-post3
  47. v-for="post3 in postList"
  48. v-bind:key="'list3-' + post3.id"
  49. v-bind:post-detail="post3"
  50. ></blog-post3>
  51. </div>
  52. <script>
  53. // 组件1:该组件通过 props 可以传递两个属性值 'title' 和 'author'
  54. Vue.component('blog-post', {
  55. props: ['title', 'author'],
  56. template: '<p> {
  57. { author }} : {
  58. { title }} </p>'
  59. })
  60. // 组件2: 又一个组件
  61. // 该组件不是传递一个字符串值,该传递一个对象。
  62. // 这样可以直接在模板里使用对象,而不必一个一个属性的传入
  63. Vue.component('blog-post2', {
  64. props: ['post2'],
  65. template: `
  66. <div class="blog-post">
  67. <p> {
  68. { post2.author}} : {
  69. { post2.title }} </p>
  70. </div>
  71. `
  72. })
  73. // 组件3: 再来一个组件
  74. // 该组件定义一个 postDetail 属性,注意在DOM中绑定属性时要使用 "v-bind:post-detail"
  75. Vue.component('blog-post3', {
  76. props: ['postDetail'],
  77. template: `
  78. <div class="blog-post">
  79. <p>{
  80. { postDetail.author }} : {
  81. { postDetail.title }}</p>
  82. </div>
  83. `
  84. })
  85. new Vue({
  86. el: '#app',
  87. data: {
  88. message: 'Hello Vue!',
  89. postList: [
  90. {
  91. id: 1, title: 'My journey with Vue', author: "Author111"},
  92. {
  93. id: 2, title: 'Blogging with Vue', author: "Author222"},
  94. {
  95. id: 3, title: 'Why Vue is so fun', author: "Author333"},
  96. ]
  97. },
  98. mounted() {
  99. this.prepareComponent();
  100. },
  101. methods: {
  102. prepareComponent() {
  103. console.log('hi, vue component mounted.');
  104. }
  105. }
  106. })
  107. </script>
  108. </body>
  109. </html>

[END]

发表评论

表情:
评论列表 (有 0 条评论,564人围观)

还没有评论,来说两句吧...

相关阅读

    相关 vue使用方法

    Vue 组件是 Vue.js 应用中可复用的代码块,通过组件可以将一个页面拆分为多个独立的部分,使代码更加清晰,结构更加简洁。以下是使用 Vue 组件的步骤: -------

    相关 如何使用vue

    目录 1:组件之间的父子关系 2:使用组件的三个步骤 3:components组件的是私有子组件 4:在main.js文件中使用Vue.component全局注册组件

    相关 vue路由

    Vue.js 组件 组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。 组件系统让我们可以用独立可复用的