Vue组件

作者: pdnbplus | 发布时间: 2024/06/25 | 阅读量: 61

Vue组件--潘登同学的前端笔记

组件

组件基础

  • 创建组件(在于APP.vue文件同级目录下的compoents中创建My_components.vue)
<!--  vue + 回车 快速生成模板 -->
  • 引用组件
<!-- 在APP.vue文件中,引入组件 -->
import MyComponent from "./components/My_components.vue";

<!-- 在JS中的watch,methods同级下,注入组件 -->
components:{
    MyComponent,
  },

<!--  再回到APP.vue的body中,调用该组件 -->
<MyComponent />
  • 组件的复用

一个组件可以视作一个独立的整体,可以复用,且互不干涉;因为你每用一次组件,就会有一个它的新实例被创建。

所以在export default下, data必须是个函数 data()

组件的组织

通常一个应用会以一棵嵌套的组件树的形式来组织:

Prop(让组件变得动态)

<!-- 第一个组件改为 对于num,因为已经绑定了,所以"5"其实是对象5,就是数字-->
<MyComponent title="组件基础" :num="5"/>
<!-- 第二个组件改为 -->
<MyComponent title="组件深入" :num="8"/>

<!-- 回到My_components.vue,在JS中的watch,methods同级下, -->
props:{
    title:{
      type:String,
      default:"default value",
    },
    num:{
      type:Number,
      default:0,
    }
  },
methods: {
  addI: function () {
    this.count += this.num;
  },
},
<!-- 组件body改为 -->
<div>
  <!-- 唯一根元素 -->
  <p>组件:{{ title }}</p>
  <div>
      <p>{{ count }}</p>
      <button @click="addI">加{{ num }}操作</button>
  </div>
</div>

Prop 验证

我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。

我们可以为组件的 prop 指定验证要求,例如你知道的这些类型。如果有一个需求没有被满足,则 Vue 会在浏览器控制台中警告你。这在开发一个会被别人用到的组件时尤其有帮助。

props: {
  // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
  propA: Number,
  // 多个可能的类型
  propB: [String, Number],
  // 必填的字符串
  propC: {
    type: String,
    required: true  // 必填的字符串
  },
  // 带有默认值的数字
  propD: {
    type: Number,
    default: 100
  },
  // 带有默认值的对象
  propE: {
    type: Object,
    // 对象或数组默认值必须从一个工厂函数获取
    default: function () {
      return { message: 'hello' }
    }
  },
  // 自定义验证函数
  propF: {
    validator: function (value) {
      // 这个值必须匹配下列字符串中的一个
      return ['success', 'warning', 'danger'].indexOf(value) !== -1
    }
  }
}

注意 注意那些 prop 会在一个组件实例创建之前进行验证,所以实例的 property (如 datacomputed 等) 在 defaultvalidator 函数中是不可用的。(但是我们的methodsdata却能使用props的值,如我们前面的methods修改一样)

  • Type的取值
[String,Number,Boolean,Array,Object,Date,Function,Symbol]

type 还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。例如,给定下列现成的构造函数:

props: {
    author: function(firstName, lastName) {
      this.firstName = firstName
      this.lastName = lastName
    }
  }

自定义事件

如果Props理解为从APP.vue传递数据(父传子),那么自定义事件就是子传父;

<!-- 在My_components.vue中,新增 -->、
<button @click="sendMessageHandle">传递数据</button>

data() {
    return {
      message:"我是一条数据",
    };
methods: {
  addI: function () {
    this.count += this.num;
  },
  <!-- onMyEvent是父级对象 -->
sendMessageHandle(){
  this.$emit("onMyEvent",this.message)
  },
},
<!-- APP.vue中 -->
<MyComponent title="组件基础" :num="5" @onMyEvent="getMyComponentMessage"/>
<!-- methods中 -->
getMyComponentMessage(data){
      console.log(data);
    }

插槽

  • 插槽内容(标签)
<!-- 新建components -->
<div>
  <h3>插槽</h3>
  <div>
      <slot></slot>
  </div>
</div>

<!-- 回到APP.vue -->
import NewComponent from "./components/New_components.vue";

data() {
  return {
    content:"我是插槽内容",
  }
},
components:{
    MyComponent,
  },
<!-- 通过组件的双标签来实现插槽功能,如果只写单标签的话,与组件功能相同 -->
<NewComponent>
  <div>{{ content }}</div>
</NewComponent>
  • 编译作用域

父级模板里的所有内容都是在父级作用域中编译的;子模板里的所有内容都是在子作用域中编译的。

写在哪就在哪声明,而不是呈现在哪就在哪声明,上面的content也是声明在APP.vue中

  • 后备内容
<!-- 如果插槽中(APP.vue中)没有传内容,还会呈现默认值 -->
<!-- 修改New_components.vue -->
<div>
  <h3>插槽</h3>
  <div>
      <slot>默认值/缺省值</slot>
  </div>
</div>
  • 具名插槽

可能在一个组件中,插槽内容分为很多条;每一条插槽内容都要放在template中,并且用 v-slot 进行绑定

<!-- 在APP.vue中 -->
<NewComponent>
  <template v-slot:header>
    <div>{{ content1 }}</div>
  </template>
  <template v-slot:body>
    <div>{{ content2 }}</div>
  </template>
  <template v-slot:footer>
  </template>
</NewComponent>

data() {
  content1:"我是插槽header",
  content2:"我是插槽body",
  content3:"我是插槽footer",
},

<!-- 修改New_components.vue -->
<div>
  <h3>插槽</h3>
  <div>
    <slot name="header">默认值/缺省值</slot>
    <hr>
    <slot name="body">默认值/缺省值</slot>
    <hr>
    <slot name="footer">默认值/缺省值</slot>
  </div>
</div>
  • 作用域插槽

让插槽内容能够访问子组件中才有的数据是很有用的;

<!-- 修改New_components.vue -->
<slot name="beiwanglu" :demo="demo1" >默认值/缺省值</slot>

data(){
    return{
        demo1:"我是demo",
    }
  },

<!-- 在APP.vue中 -->
<template v-slot:beiwanglu="b">
  <h3>{{ b.demo }}</h3>
</template>
  • 缩写

v-slot 可以被缩写为 #

动态组件&异步组件

动态组件

<!-- 新建两个组件Child1与Child2 -->
<div>
  <h3>Child1</h3>
</div>

<div>
  <h3>Child2</h3>
  <p>{{ msg }}</p>
  <button @click="clickHandle">修改</button>
</div>

  data(){
    return{
        msg:"第一次呈现数据",
    }
  },
  methods:{
    clickHandle(){
        this.msg = "new Data";
    },
  },

<!-- 新增一个组件Dycomponent -->
<div>
  <h3>我是动态组件</h3>
  <button @click="changeComponent">切换组件</button>
  <keep-alive>
      <component :is="currentComponent"></component>
  </keep-alive>
</div>

import Child1 from "./Child1.vue";
import Child2 from "./Child2.vue";

  data(){
    return {
        currentComponent:Child1,
    }
  },
  methods:{
    changeComponent(){
        if(this.currentComponent === Child1){
            this.currentComponent = Child2;
        }else{
            this.currentComponent = Child1;
        }
    },
  },
  components:{
    Child1,
    Child2,
  }

<!-- 在APP.vue下 -->
import DyComponent from "./components/DyComponent.vue";

  components:{
    DyComponent,
  },

这样就能实现,在点击切换组件后,转变成了child2,点击修改,数据变为 new Data后,在此点击切换组件(两次),回到child2后,还是new Data,起到了保留输入的情况;

异步组件

加载形式改变,在组件没有被使用的时候是不加载的,知道被使用了才加载

<!-- 原来import -->
import Child2 from "./Child2.vue";

<!-- 异步import -->
const Child2 = () => import ("./Child2")

好处: 当一次性把所有组件加载进来会非常的卡,这样加载会有效缓解