03vue2.x组件快速入门

Posted 一腔诗意醉了酒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了03vue2.x组件快速入门相关的知识,希望对你有一定的参考价值。


1. 基础

1.1 组件的命名

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

使用 kebab-case

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

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

使用 PascalCase

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

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

组件名应该始终是多个单词的,根组件 App 以及 <transition><component> 之类的 Vue 内置组件除外。

这样做可以避免跟现有的以及未来的 html 元素相冲突,因为所有的 HTML 元素名称都是单个单词的。

1.2 为什么组件的data必须是一个函数,而不能是一个对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTT65NWF-1623678791974)(%28C:%5CUsers%5Cdcs%5CDesktop%5Cnotes%5Cstudy%5CMD%5C02%E5%89%8D%E7%AB%AF%E7%9F%A5%E8%AF%86%5C05%E3%80%81Vue%E7%9B%B8%E5%85%B3%5CVue%E6%BA%90%E7%A0%81%5C04%E3%80%81%E6%B7%B1%E5%85%A5%E7%BB%84%E4%BB%B6%5Cpics%5Cimage-20210614135619093.png%29#pic_center)]

因为使用vue-cli构建工程文件来测试的时候,如果组件的data不是一个函数会报错,所以我们使用html单文件来测试。

但是很不幸的是,我们使用html来渲染也被报错了

  • 报错代码
<!DOCTYPE html>
<html lang="en">
<head>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <h1>函数data</h1>
    <func-add > </func-add>
    <func-add></func-add>
    <hr />
    <h1>对象data</h1>
    <obj-add > </obj-add>
    <obj-add></obj-add>
    <hr />
  </div>

  <div id="app2"></div>

  <script>
    Vue.component('func-add',{
      data(){
        return {
          num:1
        }
      },
      template:`<button @click='num++'>{{num1}}</button>`
    })

    Vue.component('obj-add', {
      data:{
        num1: 1
      },
      template:`<button @click='num1++'>{{num1}}</button>`
    })
    const vm = new Vue({
      el:'#app',
    })
  </script>
</body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DVhMVK1X-1623678694008)(C:\\Users\\dcs\\Desktop\\notes\\study\\MD\\02前端知识\\05、Vue相关\\Vue源码\\04、深入组件\\pics\\image-20210614152447558.png)]

data 的值是一个对象时,它会在这个组件的所有实例之间共享。想象一下,假如一个 TodoList 组件的数据是这样的:

data: {
  listTitle: '',
  todos: []
}

因为每个组件的实例都引用了相同的数据对象,更改其中一个列表的标题就会改变其它每一个列表的标题。增删改一个待办事项的时候也是如此。

取而代之的是,我们希望每个组件实例都管理其自己的数据。为了做到这一点,每个实例必须生成一个独立的数据对象。在 javascript 中,在一个函数中返回这个对象就可以了:

data: function () {
  return {
    listTitle: '',
    todos: []
  }
}

1.3 组件props的推荐用法

Prop 定义应该尽量详细。

在你提交的代码中,prop 的定义应该尽量详细,至少需要指定其类型。

详解

细致的 prop 定义有两个好处:

  • 它们写明了组件的 API,所以很容易看懂组件的用法;
  • 在开发环境下,如果向一个组件提供格式不正确的 prop,Vue 将会告警,以帮助你捕获潜在的错误来源。

好例子

props: {
  status: String
}
// 更好的做法!
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}

1.4 事件的使用

不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VGJ5DHvt-1623678694012)(C:\\Users\\dcs\\Desktop\\notes\\study\\MD\\02前端知识\\05、Vue相关\\Vue源码\\04、深入组件\\pics\\image-20210614161354213.png)]

1.5 v-model的实现原理

v-model实质上是v-bindv-on:input的结合语法糖

<template>
  <div class="main">
    <h1>使用v-model</h1>
    <input v-model='name' />
    <h1>不使用v-model</h1>
    <input :value='name1' @input='change' />
  </div>
</template>

<script>
export default {
name:'VModel',
data(){
  return {
    name:'默认名字',
    name1:'默认名字'
  }
},
methods:{
  change(e){
    console.log('发生变化', e)
    if(e.inputType === 'insertText'){
      console.log('插入',e.data)
      this.name1 += e.data
    }else{
      console.log('删除')
      let s = this.name1
      this.name1 = s.substring(0, s.length-1)
    }
  }
},
// 监听属性的变化
watch:{
name(n, o){
  console.log(`v-model导致name从--${o}--变化为--${n}--`)
},
name1(n,o){
  console.log(`模拟v-model导致name从--${o}--变化为--${n}--`)
}
}
}
</script>

1.6 插槽

插槽分类

  1. 具名插槽
  2. 默认插槽
  3. slot-scope vue 2.6+已废弃

父组件

<template>
  <div class="main">
    <center><h1>插槽</h1></center>
    <hr />
    <child>
      <!-- <div v-slot:myheader>标题</div> -->
      <!-- v-slot必须在tempalte标签中使用,不然会发生错误,如上行就是错误代码 -->

      <!-- 具名插槽 -->
      <template v-slot:myheader>
        <div id='world'>父组件插入头部</div>
      </template>
      <template>默认</template>
      <div>hello</div>

      <!-- 具名插槽的简写 -->
      <template #footer>
        <center id='hello'>{{footer}}</center>
      </template>
    </child>
  </div>
</template>

<script>
import child from './child.vue'
export default {
name:'slotParent',
components:{
  child
},
data(){
  return {
    footer:'我是父组件的脚注'
  }
}
}
</script>
<style scoped>
#world{
  color:aqua;
}
</style>
<style  >
#hello{
  color:red;
}
</style>

子组件

<template>
  <div class="main">
    <header>
      <center>头部插槽</center>
      <slot name='myheader' />
      <hr />
    </header>
    
    <main>
      <center>默认插槽</center>
      <slot  />
      <hr />
    </main>

    <footer>
      <center>脚部插槽</center>
      <slot name='footer' />
    </footer>
  </div>
</template>

<script>
export default {
name:'slotChild'
}
</script>

<style>

</style>

2. [动态组件](动态组件 & 异步组件 — Vue.js (vuejs.org))

希望某些标签的组件实例能够被在它们第一次被创建的时候缓存下来。为了解决这个问题,我们可以用一个 <keep-alive> 元素将其动态组件包裹起来。

<!-- 失活的组件将会被缓存!-->
<keep-alive>
  <component v-bind:is="currentTabComponent"></component>
</keep-alive>

3. 异步组件

通常用于路由中

component: ()=>import('./test.vue')

4. 组件使用常见问题

1. 为什么下面的代码只渲染了一个func-add组件,而且蓝色圈部分的代码失效?

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <h1>函数data</h1>
    <func-add  />
    <hr />
    <br />
    <func-add  />

  </div>

  <div id="app2"></div>

  <script>
    Vue.component('func-add',{
      props:['data'],
      data(){
        return {
          num:1
        }
      },
      template:`<button @click='num++'>{{num}}</button>`
    })

    const vm = new Vue({
      el:'#app',
    })
  </script>
</body>
</html>

在这里插入图片描述

但是把组件的名字改成<func-add></func-add>又可以正常显示。

答案:【[参考Vue的风格指南](风格指南 — Vue.js (vuejs.org))】

在这里插入图片描述


2. 同一个组件的template代码属于同一个Vue实例

在这里插入图片描述

  • 结果表明
    在这里插入图片描述

以上是关于03vue2.x组件快速入门的主要内容,如果未能解决你的问题,请参考以下文章

vue2.x 路由懒加载 优化打包体积

用vue2.x注册一个全局的弹窗alert组件

vue2.x入门学习

Vue2.x 全局组件

Vue2.x directive自定义指令

vue2.x 父组件监听子组件事件并传回信息