Vue3学习和进阶

Vue的简介

一、什么是vue?

Vue是一款用于构建用户界面的javascript框架。它基于标准的HTML、CSS、JS进行构建,并且提供的一套声明式的,组件化的编程模型,进而帮助我们高效开发用户界面。无论是复杂还是简单的界面,我们都可以用vue进行胜任的。

基本的示例如下:

import { createApp, ref } from 'vue'

createApp({
  setup() {
    return {
      count: ref(0)
    }
  }
}).mount('#app')
<div id="app">
  <button @click="count++">
    Count is: {{ count }}
  </button>
</div>

以上的示例可以完全给我们进行展示了Vue的两大核心的功能

  • 声明响应式:Vue基于标准的HTML拓展的一套模板语法,使得我们可以声明式的描述最终输出的HTML和Javascript状态直接的关系
  • 响应式:vue会进行自动的跟踪javascript状态并在其发生变化时响应式的更新DOM.

二、Vue的优势特点

1- 渐进式框架

vue是一个框架,也是一个生态。其功能已经覆盖了大部分前端的常见开发的需求了。为了考虑到web世界的多样化满足不同开发者的需求,这里vue同样的也设计的更加的灵活和“可以被逐步集成”这个特点。我们根据需求场景的不同可以用不同的方式使用Vue的

  • 独立脚本( Vue 可以以一个单独 JS 文件的形式使用,无需构建步骤!如果你的后端框架已经渲染了大部分的 HTML,或者你的前端逻辑并不复杂,不需要构建步骤,这是最简单的使用 Vue 的方式。在这些场景中你可以将 Vue 看作一个更加声明式的 jQuery 替代品 )

  • 作为 Web Component 嵌入( 你可以用 Vue 来构建标准的 Web Component,这些 Web Component 可以嵌入到任何 HTML 页面中,无论它们是如何被渲染的。这个方式让你能够在不需要顾虑最终使用场景的情况下使用 Vue:因为生成的 Web Component 可以嵌入到旧应用、静态 HTML,甚至用其他框架构建的应用中。)

  • 单页面应用 (SPA)( 一些应用在前端需要具有丰富的交互性、较深的会话和复杂的状态逻辑。构建这类应用的最佳方法是使用这样一种架构:Vue 不仅控制整个页面,还负责处理抓取新数据,并在无需重新加载的前提下处理页面切换。这种类型的应用通常称为单页应用 (Single-Page application,缩写为 SPA)。)
    Vue 提供了核心功能库和全面的工具链支持,为现代 SPA 提供了极佳的开发体验,覆盖以下方面:

    (1)客户端路由
    (2)极其快速的构建工具
    (3)IDE 支持
    (4)浏览器开发工具
    (5)TypeScript 支持
    (6)测试工具

  • 全栈 / SSR ( 纯客户端的 SPA 在首屏加载和 SEO 方面有显著的问题,因为浏览器会收到一个巨大的 HTML 空页面,只有等到 JavaScript 加载完毕才会渲染出内容。)

  • JAMStack / SSG( 如果所需的数据是静态的,那么服务端渲染可以提前完成。这意味着我们可以将整个应用预渲染为 HTML,并将其作为静态文件部署。这增强了站点的性能表现,也使部署变得更容易,因为我们无需根据请求动态地渲染页面。Vue 仍可通过激活在客户端提供交互。这一技术通常被称为静态站点生成 (SSG),也被称为 JAMStack。)

2- 单文件组件

顾名思义单文件的组件会将一个组件的逻辑(JS),模板(HTML)和样式(CSS)封装在同一个的文件里面
定义:在大多数启用了构建工具的 Vue 项目中,我们可以使用一种类似 HTML 格式的文件来书写 Vue 组件,它被称为单文件组件 (也被称为 *.vue 文件,英文 Single-File Components,缩写为 SFC)

<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
button {
  font-weight: bold;
}
</style>

3- API 风格

Vue 的组件可以按两种不同的风格书写:选项式 API 和组合式 API。

(1)、选项式 API (Options API)
使用选项式 API,我们可以用包含多个选项的对象来描述组件的逻辑,例如 data、methods 和 mounted。选项所定义的属性都会暴露在函数内部的 this 上,它会指向当前的组件实例。

示例如下:

<script>
export default {
  // data() 返回的属性将会成为响应式的状态
  // 并且暴露在 `this` 上
  data() {
    return {
      count: 0
    }
  },

  // methods 是一些用来更改状态与触发更新的函数
  // 它们可以在模板中作为事件处理器绑定
  methods: {
    increment() {
      this.count++
    }
  },

  // 生命周期钩子会在组件生命周期的各个不同阶段被调用
  // 例如这个函数就会在组件挂载完成后被调用
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

(2)、组合式 API (Composition API)
组合式API我们可以通过导入API函数的方式来描述组件的逻辑。单文件的组件中,组合式的API通常是与

下面是使用了组合式 API 与

<script setup>
import { ref, onMounted } from 'vue'

// 响应式状态
const count = ref(0)

// 用来修改状态、触发更新的函数
function increment() {
  count.value++
}

// 生命周期钩子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

两个的API具体的选择和使用?

两种 API 风格都能够覆盖大部分的应用场景。它们只是同一个底层系统所提供的两套不同的接口。实际上,选项式 API 是在组合式 API 的基础上实现的!关于 Vue 的基础概念和知识在它们之间都是通用的。

二者比较具体使用:

选项式 API 以“组件实例”的概念为中心 (即上述例子中的 this),对于有面向对象语言背景的用户来说,这通常与基于类的心智模型更为一致。同时,它将响应性相关的细节抽象出来,并强制按照选项来组织代码,从而对初学者而言更为友好

组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,也需要你对 Vue 的响应式系统有更深的理解才能高效使用。相应的,它的灵活性也使得组织和重用逻辑的模式变得更加强大

  • 当你不需要使用构建工具,或者打算主要在低复杂度的场景中使用 Vue,例如渐进增强的应用场景,推荐采用选项式 API
  • 当你打算用 Vue 构建完整的单页应用,推荐采用组合式 API + 单文件组件。

Vue3的介绍和具体使用

一、基础知识

1- Vue3概述

Vue3是一个流行的JavaScript框架,用于构建用户界面。它是Vue.js框架的下一个主要版本,由Evan You领导的Vue.js团队开发

Vue3于2020年9月正式发布,相比于Vue2,Vue3在性能、响应式系统、TypeScript支持、Composition API等方面进行了大量改进和优化。

Vue3的响应式系统采用了ES6 Proxy对象,提高了响应式系统的性能和稳定性,并且允许更好的TypeScript支持。Composition API是一个新的API,它允许按逻辑组织代码,提高代码的可维护性和重用性。此外,Vue3还具有更好的Tree-shaking支持,提高了应用程序的性能。

总体而言,Vue3是一个优秀的框架,它在性能、开发体验和可维护性方面都有所提高,是开发现代Web应用程序的不错选择

2- Vue3的特性和优势

Vue3作为目前Vue.js框架的最新版本,有许多优势和特性的,具体包括如下:

  • 更快的渲染速度和更小的包体积:Vue3通过优化虚拟DOM的实现和使用静态提升技术等方法,显著提高渲染速度和减小了包体积。
  • 有更好的TS支持:Vue3中对TypeScript的支持更加友好,包括提供了更完整的类型定义和支持装饰器的语法
  • 组合式API(Composition API):Vue3里面引入了Composition API,提供了更灵活、更可重用和更易于测试的组件逻辑复用方式。
  • 更好的响应式系统:Vue3的响应式通过proxy代理对象代替了Object.defineProperty实现,提高了性能并且可以更好的支持嵌套对象和数组。
  • 更好的调试工具支持:Vue3提供了更好的调试工具的支持,包括可视化组件树和性能分析工具等。
  • 更好的Three Shaking的支持:Vue3通过优化内部使用的依赖关系,更好的支持Tree Shaking,减小了包体积。

总的来说:Vue3给我们带来了更快,更灵活,更易于使用,更好的开发体验和更好的性能的。

3- Vue3的生命周期

Vue3的生命周期相比较Vue2来说进行了一些优化和调整,不过总得来说大同小异的。以下是Vue3的生命周期函数:

  • 1,beforeCreate:实例初始化之后,数据观测(data observer)和event/watcher事件配置之前被调用的。
  • 2,created:实例已经创建完成后被调用。在这个阶段,模板已经编译完成了,但是还没有挂载到DOM上面。
  • 3,beforeMount:在挂载开始之前被调用,即在render函数首次被调用之前。
  • 4,mount:实例挂载完成之后被调用,这个时候DOM元素已经完全被渲染出来了。
  • 5,beforeUpdate:数据更新时被调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子函数中进行更改数据。
  • 6,update:数据更改导致虚拟DOM重新渲染和打补丁完成时候调用。
  • 7,beforeUnmount:实例卸载之前调用,可以在这里做一些清理工作。
  • 8,unmounted:实例卸载之后调用,这里没有 this,所以无法访问数据和方法。
  • 9,errorCaptured:捕获子孙组件抛出的异常。被调用时,可以返回 false 以阻止该异常继续向上传播。

注意点:Vue3去掉了beforeDestroy和destroyed两个生命周期,取而代之的是beforeUnmount和unmounted。因为在Vue3中,所有的组件都被设计成了Teleport,即可以被迁移的,而不是被销毁的。因此,在组件卸载之前,会执行beforeUnmount,而在组件被卸载之后,会执行unmounted。

4- Vue3的模板语法

  • 1,插值表达式
    Vue3中的插值表达式使用双大括号{{}},例如:{{ message }}。Vue3也支持在插值表达式中使用JavaScript表达式。
<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
    <p>{{ num1 + num2 }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      title: 'Hello Vue 3!',
      message: 'This is a message',
      num1: 10,
      num2: 20
    }
  }
}
</script>
  • 2,指令
    Vue3中的指令使用v-前缀,例如:v-if、v-for、v-bind等。Vue3还引入了一些新的指令,如v-model的语法被改变,现在使用v-model:value和v-model:modifier来实现双向绑定和修饰符。此外,还有一些新的指令,如v-html、v-show、v-suspense等。

v-bind用于绑定HTML属性和组件props,可以简写为“:”

<template>
  <div>
    <img :src="imageUrl" alt="image">
    <my-component :prop1="data1" :prop2="data2"></my-component>
  </div>
</template>

<script>
export default {
  data() {
    return {
      imageUrl: 'https://example.com/image.png',
      data1: 'prop1',
      data2: 'prop2'
    }
  }
}
</script>

v-on用于绑定事件处理函数,可以简写为“@”

<template>
  <div>
    <button @click="clickHandler">Click me</button>
  </div>
</template>

<script>
export default {
  methods: {
    clickHandler() {
      console.log('button clicked');
    }
  }
}
</script>

v-if用于条件渲染,根据表达式的值决定是否渲染该元素

<template>
  <div>
    <p v-if="show">This is a paragraph</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      show: true
    }
  }
}
</script>

v-for用于循环渲染,渲染数组中的每一个元素

<template>
  <div>
    <ul>
      <li v-for="(item, index) in items" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      items: ['item1', 'item2', 'item3']
    }
  }
}
</script>

5,Vue3的计算属性和侦听器

计算属性是根据已有的属性值(响应式依赖)计算出一个新的值,相当于是一个带有缓存的方法,只要依赖的数据没有改变,计算属性就不会重新计算。

例如,我们可以使用计算属性来根据数据列表过滤出需要展示的数据

<template>
  <div>
    <input type="text" v-model="keyword" />
    <ul>
      <li v-for="item in filteredList" :key="403 Forbidden">
        {{ item.title }}
      </li>
    </ul>
  </div>
</template>

<script>
import { ref, computed } from 'vue';

export default {
  setup() {
    const list = ref([
      { id: 1, title: 'Apple' },
      { id: 2, title: 'Banana' },
      { id: 3, title: 'Orange' },
      { id: 4, title: 'Pear' },
    ]);

    const keyword = ref('');

    const filteredList = computed(() => {
      return list.value.filter((item) => {
        return item.title.toLowerCase().indexOf(keyword.value.toLowerCase()) !== -1;
      });
    });

    return {
      keyword,
      filteredList,
    };
  },
};
</script>

侦听器是用于监听数据变化并触发一些操作的方法,它可以监听到数据的变化并执行相应的操作。在 Vue3 中,我们可以使用 watch 函数来创建侦听器:

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>

<script>
import { ref, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);

    watch(count, (newValue, oldValue) => {
      console.log(`count changed from ${oldValue} to ${newValue}`);
    });

    function increment() {
      count.value++;
    }

    return {
      count,
      increment,
    };
  },
};
</script>

上面的代码中,我们使用 watch 函数来监听 count 变量的变化,并在变化时打印出新旧值。当用户点击 “Increment” 按钮时,count 变量的值会增加,并触发 watch 函数。

6、Vue3的事件处理

在Vue3中,事件处理是通过在模板中使用@符号来绑定事件。例如,我们可以使用@click来绑定click事件,如下所示:

<template>
  <button @click="handleClick">Click me!</button>
</template>

在上面的代码中,我们绑定了一个click事件到button元素,并指定了一个名为handleClick的方法来处理该事件。

与传统的事件绑定不同,Vue3的事件处理方法使用了一个特殊的修饰符语法。这些修饰符可以用来指定事件的一些行为,例如阻止事件冒泡或取消默认行为。以下是一些常用的事件修饰符:

  • .stop:阻止事件冒泡。
  • .prevent:取消事件的默认行为。
  • .capture:事件在捕获阶段被处理。
  • .self:只当事件发生在该元素本身而不是子元素时触发。
  • .once:事件只会触发一次。
  • .passive:告诉浏览器不需要等待事件处理函数完成就可以滚动页面。

下面是使用装饰费的示例:

<template>
  <div @click.stop.prevent="handleClick">Click me!</div>
</template>

在上面的代码中,我们使用了.stop和.prevent修饰符来阻止事件冒泡和取消默认行为。

除了常规的DOM事件外,Vue3还提供了自定义事件。我们可以使用$emit方法来触发自定义事件,然后在父组件中使用v-on来监听这些事件。以下是一个使用自定义事件的示例:

<template>
  <button @click="handleClick">Click me!</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('custom-event', 'Hello, world!');
    }
  }
};
</script>

在上面的代码中,我们定义了一个名为custom-event的自定义事件,并在点击事件中使用$emit方法触发该事件。在父组件中,我们可以使用v-on:custom-event来监听该事件。例如:

<template>
  <my-component @custom-event="handleCustomEvent"></my-component>
</template>

<script>
import MyComponent from './MyComponent.vue';

export default {
  components: {
    MyComponent
  },
  methods: {
    handleCustomEvent(message) {
      console.log(message); // 输出:Hello, world!
    }
  }
};
</script>

在上面的代码中,我们在父组件中使用@custom-event来监听自定义事件,并在handleCustomEvent方法中获取传递的参数。

二、组件化开发

1- Vue3的组件化开发

Vue3 是一个基于组件化开发的前端框架,因此组件化开发是 Vue3 的核心。Vue3 组件是由一组可复用的模板、样式和逻辑组成的,它可以被其他组件或者页面引用。

组件的核心是一个 Vue 实例,它可以使用 Vue 提供的选项进行配置,例如 data、methods、computed 等选项。一个 Vue 组件可以接受父组件传递的参数,也可以向父组件发送事件。

Vue3 提供了一个 defineComponent 函数来定义组件,这个函数接收一个配置对象作为参数,配置对象中包含了组件的各种选项。
下面是关于Vue组件的简单示例:

<template>
  <div class="counter">
    <h1>{{ count }}</h1>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { defineComponent, ref } from 'vue';

export default defineComponent({
  name: 'Counter',
  setup() {
    const count = ref(0);

    const increment = () => {
      count.value++;
    };

    return {
      count,
      increment,
    };
  },
});
</script>

<style>
.counter {
  display: flex;
  flex-direction: column;
  align-items: center;
}
</style>

在这个组件里面,我们使用Vue3的defineComponent函数定义一个名为Counter的组件。组件中有一个count变量和一个increment方法,count变量的初始值是0,increment方法每次调用可以把count值加1。我们使用了插值表达式将 count 的值渲染到页面中,并使用 @click 指令绑定了 increment 方法。

这个示例展示了 Vue3 组件的基本结构,包括模板、脚本和样式。在 setup 函数中定义组件的状态和行为,然后将它们返回,让模板可以访问。

2- Vue的组件通信详解

Vue3中的组件通信可以使用props和事件两种方式来实现。

  • 1,props通信如下:
    props主要是父组件向子组件传递数据的方式。子组件通过props进行接手数据,这种数据流是单向的。即只能从父组件流向子组件的。
    父组件中使用props向子组件进行传递数据

Vue2里面的写法

<template>
  <child-component :message="messageFromParent" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      messageFromParent: 'Hello from parent'
    }
  }
}
</script>

子组件中,我们通过props进行接收数据

<template>
  <div>{{ message }}</div>
</template>
<script>
export default {
  props: {
    message: {
      type: String,
      default: ''
    }
  }
}
</script>

vue3里面的写法

<template>
    <div>这里是父组件</div>
    <input type="text" v-model="inputMsg"/>
    
    <div>
        inputMsg:{{inputMsg}}
    </div>
    <div>
        msg:{{msg}}
    </div>
    
    <div>
        <button @click="changeMsg">点击修改</button>
    </div>
    <div style="margin: 10px;">分割线-------------------------</div>

<childView
    :toMsg="msg"
    :toFunc="func"
></childView>

</template>

<script setup>
import { reactive, ref } from 'vue';
import  childView  from './edit.vue'

const inputMsg = ref('这里是父组件的消息')
const msg = ref('')

const func = () =>{
    changeMsg()
}

const changeMsg = () => {
    msg.value = inputMsg.value
}

</script>

子组件

<template>
    <div>
        <div>这里是子组件</div>
        <div>收到父组件消息toMsg:{{toMsg}}</div>
    </div>
    <div>
        <button @click="toFunc">点击执行收到的父组件方法</button>
    </div>
    <div>
        <button @click="changeMsg">点击修改toMsg</button>
    </div>
    
</template>

<script setup>
    // 需要定义defineProps
const props = defineProps({
    toMsg: {
        type: String,
        default: 100,
    },
    toFunc: {
        type: Function,
        default: async () => {},
    }
})

const changeMsg = () => {
    props.toMsg = "子组件修改"
}


//或者直接接受,不设定类型与默认值
const props = defineProps(['toMsg '])
</script>

<style>
</style>

对于取值:setup中要通过props.msg取到,模板中直接msg取到

  • 2,事件
    事件是一种在子组件向父组件通信的方式

vue2里面的写法

在子组件中定义事件:

<template>
  <button @click="onClick">Click me</button>
</template>
<script>
export default {
  methods: {
    onClick() {
      this.$emit('button-clicked', 'Button clicked in child component');
    }
  }
}
</script>

在父组件中,通过v-on(缩写@)指令监听子组件触发的事件:

<template>
  <child-component @button-clicked="onButtonClicked" />
</template>
<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    onButtonClicked(message) {
      console.log(message);
    }
  }
}
</script>

这样,当子组件中的按钮被点击时,会触发button-clicked事件,父组件会调用onButtonClicked()方法,并接收子组件传递的数据。

vue3里面的写法
emit是最常见的用于子组件向父组件传递消息的方法vue3使用使用defineEmits来声明emit,它接收内容与emit选项是一致的。

(1)用法一:给父组件发送自定义事件

// ----------子组件--------
  <button @click="btn">点击</button>
<script setup>
import {defineEmits} from 'vue'
const emit = defineEmits(['emit']) //数组里可以有多个自定义方法名
//或者使用ts约束自定义方法的参数
const emit = defineEmits<{
  (e:'getAge',age:number):void //设置自定义函数名称,参数类型与返回值类型
  // 可在此设置第二个自定义函数
}>()
 
function btn() {
  emit('getAge',18)
}
</script>
 
 
// ---------父级组件中--------
 
// 在父级组件中,使用子级的自定义事件,在html中去写@自定义事件名称=事件名称(就是在子组件中emits的第一个参数)
  <HelloWorld @getAge="handleAge"/>
<script setup>
import HelloWorld from '@/components/HelloWorld'
// 函数中data是个形参,为子级传递过来的数据
const handleAge = function (data) {
  console.log(data)
}
</script>

(2)用法二:使用modelValue直接更新父组件数据

除了props和事件,Vue3中还提供了provide/inject、$refs等方式来实现组件通信。

//结构  
// 父组件:
  <CHild v-model:test="test"></CHild>
 
//逻辑
let test =ref()
 
 // 子组件
 //逻辑
const props = defineProps({
test:'',
})
const emit = defineEmits(['update:test']);  //这个test就是接收的props
const resetTest =() =>{
//更新test给父组件
emit('update:test','最新数据')
}

这样父组件不需要自定义事件就能接受到最新的test数据。!

注意:不管使用props 或者emits 在vue3 里面都需要使用 defineProps 和 defineEmits 声明。

Vue2 里面父组件中调用子组件方法

方法1:通过$refs来进行调用。

// 子组件
 <template>
     <div>我是子组件</div>
    </template>
    <script>
        export default {
            data() {
                return {
                    name: 'jack'
                }
            },
            methods: {
                childrenFuc() {
                    //在这里做某些子组件的操作。更菜子组件的值等等
                    this.name = 'Tom'
                }
            }
        }
    </script>

// 父组件
    <template>
        <childBody ref="childRef"></childBody>
        <button @click="handleClick">点击按钮</button>
    </template>
    <script>
        export default {
            data() {
                return {
                    name: 'jack'
                }
            },
            methods: {
                handleClick() {
                    //通过点击事件触发子组件的函数方法
                    this.$refs.childRef.childrenFuc();
                }
            }
        }
    </script>

方法2:使用emit 和 emit和emit和on的方法

在子组件的mounted或者created定义需要触发的函数

// 子组件
 <template>
        <div>我是子组件</div>
    </template>
    <script>
        export default {
            data() {
                return {
                    name: 'jack'
                }
            },
            mounted() {

                //使用$nextTick方法,确保dom渲染完毕后加载该函数。
                this.$nextTick(function () {
                    this.$on("childrenFuc", () => {
                        //在这里做某些子组件的操作。更菜子组件的值等等
                        this.name = 'Tom'
                    })
                })

            }
        }
    </script>
// 父组件

    <template>
        <childBody ref="childRef"></childBody>
        <button @click="handleClick">点击按钮</button>
    </template>

    <script>
        export default {
            data() {
                return {

                }
            },
            methods: {
                handleClick() {
                    //触发子组件的方法。
                    this.$refs.childRef.$emit("childrenFuc");
                }
            },
        }
    </script>

vue3 里面父组件中调用子组件方法
1:通过ref直接调用子组件的方法 ref=“RefChild”;

2:在函数中写 RefChild.value.reset();, “reset”为子组件中定义的函数名。

3:子组件定义一个函数 reset(),使用defineExpose抛出,让父组件调用即可。

4:这个方法也可以进行传值,在括号中传入值,子组件接收即可 。

父组件

<template>
  <div class="vc-box">
    <el-button-group>
          <el-button
            :type="tabletype === '1' ? 'primary' : ''"
            @click="selectTable('1')"
            >按钮1</el-button
          >
          <el-button
            :type="tabletype === '2' ? 'primary' : ''"
            @click="selectTable('2')"
            >按钮2</el-button
          >
          <el-button
            :type="tabletype === '3' ? 'primary' : ''"
            @click="selectTable('3')"
            >按钮3</el-button
          >
    </el-button-group>
    <Child
          ref="RefChild"
          @onselect="handleCriterionChange"
          v-if="tabletype === '测试'"
    ></Child>
 
  </div>
</template>
 
 
 
<script name="index" setup lang="ts">
import Child from '@/modular/analysis/components/child.vue';
 
const tabletype = ref();
    
// 获取子组件的引用
const RefChild = ref();
 
const selectTable = i => {
   if (RefChild.value) {
     RefChild.value.reset();
   }
}
 
const handleCriterionChange = (type: number) => {
     console.log('输出点击事件')
}
 
</script>

子组件

<template>
  <el-form :model="criterionForm">
    <el-form-item label="规范类别">
      <el-select
        v-model="criterionForm.criterionType"
        class="m-2"
        style="width: 130px"
        placeholder="Select"
        size="default"
        @change="type => emits('onselect', type)"
      >
        <el-option
          v-for="item in criterionOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
    </el-form-item>
  </el-form>
</template>
<script setup lang="ts">
import { Ref } from 'vue';
 
const emits = defineEmits<{ (e: 'onselect', value: number): void }>();
 
const criterionForm: Ref<{ criterionType: number }> = ref({
  // 默认展示全部
  criterionType: 0
});
 
const reset = () => {
  criterionForm.value.criterionType = 0;
};
 
const criterionOptions = [
  {
    label: '全部',
    value: 0
  },
  {
    label: '合格',
    value: 1
  },
  {
    label: '不合格',
    value: 2
  }
];
 
defineExpose({
  reset
});
</script>

Vue3里面也支持provide / inject(祖孙、父子组件)
Vue3里面兄弟组件目前使用mitt,vue到3.0之后好像取消了bus全局事件总线,选择使用mitt作为兄弟组件间通信和传参的方式。mitt的使用方法有两种:可以单独创建一个文件,哪里要用就引入它;也可以 main.js 中挂载全局属性;

3- Vue3的插槽

插槽是Vue3中用于在组件之间共享内容的一种机制。简单来说,它们允许我们将内容插入到组件的特定区域中。
Vue3的插槽功能非常强大,它允许我们在组件间灵活地分发和接收内容。无论是默认插槽、具名插槽、作用域插槽还是动态插槽,都能满足我们在实际开发中的各种需求。

Vue3中的插槽分为四种类型:

3.1 - 默认插槽
3.2 - 具名插槽
3.3 作用域插槽
3.4动态插槽

Vue3中的插槽是一个强大的工具,可以帮助我们更好地管理组件之间的内容共享。通过使用插槽,我们可以更好地控制组件中的内容,使其更易于维护和扩展。如果您正在使用Vue3构建Web应用程序,插槽是一个不容错过的功能。

默认插槽
默认插槽是最简单的插槽类型。如果我们在子组件中没有指定插槽内容,那么父组件中的内容将会被默认插入。以下是一个例子:
简单的实例如下:

<!-- 父组件 -->
<template>
  <div>
    <h1>{{ title }}</h1>
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  props: {
    title: {
      type: String,
      required: true
    }
  }
}
</script>

在父组件中,我们定义了一个插槽,它表示该组件可以接收子组件传递过来的任何内容,并将其渲染在插槽所在的位置。

现在,我们可以在父组件标签内传入任何我们想要展示的内容,例如:

<!-- 使用父组件,并在其中传入一些内容 -->
<my-component title="这是标题">
  <p>这是一些内容</p>
  <ul>
    <li>列表项1</li>
    <li>列表项2</li>
  </ul>
</my-component>

具名插槽
具名插槽允许我们在子组件中定义多个插槽,并通过名称来区分它们。这样,我们就可以在父组件中为每个插槽指定不同的内容。以下是一个例子:

<!-- ParentComponent.vue -->
<template>
  <div>
    <h2>父组件</h2>
    <ChildComponent>
      <template #header>
        <h3>这是头部插槽的内容。</h3>
      </template>
      <template #footer>
        <p>这是底部插槽的内容。</p>
      </template>
    </ChildComponent>
  </div>
</template>

<!-- ChildComponent.vue -->
<template>
  <div>
    <h3>子组件</h3>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

在上述示例中,我们在父组件的模板中为ChildComponent定义了两个具名插槽:header和footer。

在子组件的模板中,我们通过使用元素的name属性来定义具名插槽,将插槽内容分发到相应位置。这样,我们可以在父组件中根据需求为子组件的不同插槽传递不同的内容

作用域插槽

<!-- ParentComponent.vue -->
<script setup lang="ts">
import ChildSlot from "@/views/ChildSlot/ChildSlot.vue";
import { reactive } from "vue";
</script>

<template>
  <div>
    <h2>父组件</h2>
    <ChildSlot>
      <template #default="props">
        <p>{{ props.message }}</p>
      </template>
    </ChildSlot>
  </div>
</template>

<style scoped></style>


<!-- ChildComponent.vue -->
<template>
  <div>
    <h3>子组件</h3>
    <slot :message="message"></slot>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
</script>

在上述示例中,我们在父组件中使用作用域插槽,并通过props参数访问子组件的数据。

动态插槽

<!-- ParentComponent.vue -->
<script setup lang="ts">
import ChildSlot from "@/views/ChildSlot/ChildSlot.vue";
import { ref } from "vue";
const slotName = ref<string>("footer");
</script>

<template>
  <div>
    <h2>父组件</h2>
    <ChildSlot>
      <template #[slotName]>
        <h3>动态插槽的内容。</h3>
      </template>
    </ChildSlot>
  </div>
</template>

<style scoped></style>

<!-- ChildComponent.vue -->
<template>
  <div>
    <h3>子组件</h3>
    <slot name="header"></slot>
    <slot></slot>
    <slot name="footer"></slot>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
</script>

在上述示例中,通过改变变量slotName,可使动态插槽的内容。插入到不同的位置

相关推荐

  1. Vue3学习

    2024-04-09 00:26:03       14 阅读
  2. vue3

    2024-04-09 00:26:03       18 阅读
  3. 19篇 vue3

    2024-04-09 00:26:03       18 阅读
  4. 【Erlang学习3、列表推导

    2024-04-09 00:26:03       38 阅读
  5. vue

    2024-04-09 00:26:03       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-09 00:26:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-09 00:26:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-09 00:26:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-09 00:26:03       18 阅读

热门阅读

  1. 外贸建站公司排名

    2024-04-09 00:26:03       14 阅读
  2. 前端开发教程

    2024-04-09 00:26:03       16 阅读
  3. SpringBoot实现增删改查

    2024-04-09 00:26:03       13 阅读
  4. 复试专业课问题

    2024-04-09 00:26:03       13 阅读
  5. css外边距合并和BFC

    2024-04-09 00:26:03       12 阅读
  6. Leetcode 8. 字符串转换整数 (atoi)

    2024-04-09 00:26:03       13 阅读
  7. 蓝桥杯嵌入式之模块驱动

    2024-04-09 00:26:03       14 阅读