VUE——组件

本文详细介绍了Vue的组件系统,包括组件的概念、全局与局部注册、SFC(Single-File-Component)、父向子传值的props机制、单向数据流、子向父传值的自定义事件、属性透传以及插槽和动态组件的使用。同时,提到了路由在单页面应用中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

组件

     概念:

      组件的定义:

      组件注册:

       全局注册

       局部注册

       SFC:Single-File-Component

父向子传值

静态&动态传值

类型约束&函数校验

单向数据流

子向父传值

透传(Attributes)

插槽

动态组件

路由

组件

             页面布局的本质是盒子,盒子就是标签

             页面布局的本质是盒子,盒子就是组件

     概念:

        组件就是功能模块的封装

        组件是构成页面中独立结构单元,组件主要以独立页面结构形式存在,不同组件也具有基本交互功能。

       功能模块:一个页面分成三个层

       结构层、表现层、行为层

      

        一个组件的基本步骤:定义,引入,注册,使用。

      组件的定义:

       当使用构建步骤时,我们一般会将 Vue 组件定义在一个单独的 .vue 文件中,这被叫做单文件组件 (简称 SFC)

      组件注册

       组件的使用需要用import引入,然后通过components来注册组件,然后组件的使用,和标签一样。组件将会以其注册时的名字作为模板中的标签名。

        组件注册还分为全局注册和局部注册:

       全局注册

        一个全局的变量,可以在任意的组件使用;任何“页面”都可以使用,比如“导航栏”

        注册方法:先引入,然后使用app.component()方法,app.component()方法可以被链式调用。

       

    全局注册虽然很方便,但有以下几个问题:

  • 全局注册,但并没有被使用的组件无法在生产打包时被自动移除 (也叫“tree-shaking”)。如果你全局注册了一个组件,即使它并没有被实际使用,它仍然会出现在打包后的 JS 文件中。
  • 全局注册在大型项目中使项目的依赖关系变得不那么明确。在父组件中使用子组件时,不太容易定位子组件的实现。和使用过多的全局变量一样,这可能会影响应用长期的可维护性。
  • 相比之下,局部注册的组件需要在使用它的父组件中显式导入,并且只能在该父组件中使用。它的优点是使组件之间的依赖关系更加明确,并且对 tree-shaking 更加友好

       局部注册

        方法:使用components选项;

        

       SFC:Single-File-Component

        Vue 的单文件组件 ( *.vue 文件,英文 Single-File Component,简称 SFC) 是一种特殊的文件格式,使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中。

父向子传值

      首选props;

       props后的参数可以是数组,也可以是对象

        当一个值被传递给 prop 时,它将成为该组件实例上的一个属性。该属性的值可以像其他组件属性一样,在模板和组件的 this 上下文中访问。

一个组件可以有任意多的 props,默认情况下,所有 prop 都接受任意类型的值。

       

      

静态&动态传值

       

        

        动静态都可以传递不同的值:可以传Number、Boolean、Array、Object

        动态传输对象:   

            

        prop 被用于传入初始值;而子组件想在之后将其作为一个局部数据属性。在这种情况下,最好是新定义一个局部数据属性,从 props 上获取初始值即可:

       

       

类型约束&函数校验

props: {

    // 基础类型检查

    //(给出 `null` 和 `undefined` 值则会跳过任何类型检查)

    propA: Number,

    // 多种可能的类型

    propB: [String, Number],

    // 必传,且为 String 类型

    propC: {

      type: String,

      required: true,

    },

    // Number 类型的默认值

    propD: {

      type: Number,

      default: 100,

    },

    // 对象类型的默认值

    propE: {

      type: Object,

      // 对象或者数组应当用工厂函数返回。

      // 工厂函数会收到组件所接收的原始 props

      // 作为参数

      default(rawProps) {

        return { message: "hello" };

      },

    },

    // 自定义类型校验函数

    propF: {

      validator(value) {

        // The value must match one of these strings

        return ["success", "warning", "danger"].includes(value);

      },

    },

    // 函数类型的默认值

    propG: {

      type: Function,

      // 不像对象或数组的默认,这不是一个工厂函数。这会是一个用来作为默认值的函数

      default() {

        return "Default function";

      },

    },

  }

  

        校验选项中的 type 可以是下列这些原生构造函数:

String,Number,Boolean,Array,Object,Date,Function,Symbol

        另外,type 也可以是自定义的类或构造函数,Vue 将会通过 instanceof 来检查类型是否匹配。

单向数据流

        所有的 props 都遵循着单向绑定原则,props 因父组件的更新而变化,自然地将新的状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。

       另外,每次父组件更新后,所有的子组件中的 props 都会被更新到最新值,这意味着你不应该在子组件中去更改一个 prop

        

子向父传值

        通过自定义事件来传值

        组件实例提供了一个自定义事件系统,我们就通过自定义事件来实现子向父传值:父组件可以通过 v-on  @ 来选择性地监听子组件上抛的事件,就像监听原生 DOM 事件那样

    子组件可以通过调用内置的 $emit 方法,通过传入事件名称来抛出一个事件:            

透传(Attributes)

        “透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。

        当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。

        对 class 和 style 的合并

        v-on 监听器继承

        如果不想要一个组件自动地继承 attribute,你可以在组件选项中设置 inheritAttrs: false

        

        透传进来的 attribute 可以在模板的表达式中直接用 $attrs 访问到

        

            

        

插槽

        <slot> 元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。

        了解到组件能够接收任意类型的 JavaScript 值作为 props,但组件要如何接收模板内容呢?在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。

        <slot> 元素可以有一个特殊的 attribute name,用来给各个插槽分配唯一的 ID,以确定每一处要渲染的内容,这类带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 <slot> 出口会隐式地命名为“default”。

        要为具名插槽传入内容,我们需要使用一个含 v-slot 指令的 <template> 元素,

        v-slot 有对应的简写 #

        

        最终渲染出来的结果为:

        

        

动态组件

        

        在上面的例子中,被传给 :is 的值可以是以下几种: 

  • 被注册的组件名
    • 导入的组件对象

        你也可以使用 is attribute 来创建一般的 HTML 元素。

        当使用 <component :is="..."> 来在多个组件间作切换时,被切换掉的组件会被卸载

路由

        服务端路由指的是服务器根据用户访问的 URL 路径返回不同的响应结果。当我们在一个传统的服务端渲染的 web 应用中点击一个链接时,浏览器会从服务端获得全新的 HTML,然后重新加载整个页面。

        然而,在单页面应用中,客户端的 JavaScript 可以拦截页面的跳转请求,动态获取新的数据,然后在无需重新加载的情况下更新当前页面。这样通常可以带来更顺滑的用户体验,尤其是在更偏向“应用”的场景下,因为这类场景下用户通常会在很长的一段时间中做出多次交互。

        在这类单页应用中,“路由”是在客户端执行的。一个客户端路由器的职责就是利用诸如 History API 或是 hashchange 事件这样的浏览器 API 来管理应用当前应该渲染的视图。

        SPA:单页面应用

        基于component的原生实现

<template>
  <div>
    <A href="#about">关于我们</A> | <A href="#contact">联系我们</A> |
    <A href="#products">产品中心</A>

    <!-- component是内置的组件,用来动态的显示组件 -->
    <component :is="currentComponent" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import About from "./views/About.vue";
import Contact from "./views/Contact.vue";
import Products from "./views/Products.vue";

/** 属性值是A链接的hash值*/
const router = {
  about: About,
  contact: Contact,
  products: Products,
};

export default defineComponent({
  data() {
    return { currentComponent: About };
  },
  components: {},
  methods: {},
  created() {
    const hash = window.location.hash;
    this.currentComponent = router[hash.slice(1)];
  },
  mounted() {
    /** 箭头函数的目的是为了让this指向当前组件*/
    const hashChangeFn = () => {
      const hash = window.location.hash;
      console.log(hash);
      this.currentComponent = router[hash.slice(1)];
    };
    /** 没有监听点击事件*/
    window.addEventListener("hashchange", hashChangeFn);
  },
});
</script>

<style lang="scss" scoped></style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值