Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记

本文主要是介绍Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Vue CLI安装和使用

  1. 全局安装最新vue3
npm install @vue/cli -g
  1. 升级Vue CLI:
    如果是比较旧的版本,可以通过下面命令来升级
npm update @vue/cli -g

通过脚手架创建项目

vue create 01_product_demo

Vue3父子组件的通信

父传子

父组件

<template><div><div class="item" v-for="(item,index) in user_list" :key="index"><user-component :name="item.name" :age="item.age"></user-component></div></div>
</template><script>import UserComponent from './components/UserComponent'export default {components:{UserComponent},data(){return {user_list:[{name:'why',age:18},{name:'zhang',age:26},]}}}
</script><style scoped></style>

子组件 UserComponent.vue

<template><div><div>名字:{{ name }}</div><div>年龄:{{ age }}</div></div>
</template><script>export default {props:{name:{type:String,default:''},age:{type:Number,default:0},// 对象类型friend:{type:Object,default:()=>({name:"james"})},// 数组类型hobbies:{type:Array,default:()=>['篮球','rap','唱跳']}}}
</script><style scoped></style>

子传父

父组件

<template><div><div>{{ counter }}</div><JiaComponent @jia="jia"></JiaComponent> <JianComponent @jian="jian"></JianComponent> </div>
</template><script>import JiaComponent from './JiaComponent'import JianComponent from './JianComponent'export default {components:{JiaComponent,JianComponent},data(){return {counter:1}},methods:{jian:function(data){this.counter = this.counter - data;},jia:function(data){this.counter = this.counter + data;}}}
</script><style scoped></style>

**子组件1 JiaComponent.vue **

<template><div><div><button @click="jia(1)">+1</button><button @click="jia(5)">+5</button><button @click="jia(10)">+10</button></div></div>
</template><script>export default {emits:['jia'], // 使用的时候会有提醒// emits:{//   // 验证//   jia:function(data){//     if(data <= 5){//       return true//     }//     return false//   }// },methods:{jia(data){this.$emit('jia',data);}}}
</script><style scoped></style>

** 子组件2 JianComponent.vue **

<template><div><div><button @click="jian(1)">-1</button><button @click="jian(5)">-5</button><button @click="jian(10)">-10</button></div></div>
</template><script>export default {methods:{jian(data){this.$emit("jian",data);}}}
</script><style scoped></style>

插槽基本使用

父组件

<template><div><TitleComponents title="标题" desc="描述描述描述描述描述"></TitleComponents> <!-- 1.插入button --><TitleComponents title="标题" desc="描述描述描述描述描述"><button>按钮</button></TitleComponents><!-- 2.插入a链接 --><TitleComponents title="标题" desc="描述描述描述描述描述"><a href="https://www.baidu.com">百度一下</a></TitleComponents><!-- 3.插入image --><TitleComponents title="标题" desc="描述描述描述描述描述"><img src="https://gimg3.baidu.com/search/src=http%3A%2F%2Fpics6.baidu.com%2Ffeed%2F34fae6cd7b899e512cb62692d10fdf3ec9950db4.jpeg%40f_auto%3Ftoken%3D8ce9dbae74003846c318068640c41183&refer=http%3A%2F%2Fwww.baidu.com&app=2021&size=f360,240&n=0&g=0n&q=75&fmt=auto?sec=1698944400&t=e504855a1a7b815dfa76940bb9ac2a07" /></TitleComponents><!-- 4. 默认显示 --><TitleComponents title="标题" desc="描述描述描述描述描述"></TitleComponents> </div>
</template><script>
import TitleComponents from './TitleComponents.vue'export default {components:{TitleComponents}}
</script><style scoped></style>

子组件 TitleComponents.vue

<template><div><h1>{{ title }}</h1><div>{{ desc }}</div><slot><div>这里是默认内容</div></slot></div>
</template><script>export default {props:{title:{type:String,default:'默认标题'},desc:{type:String,default:''}}}
</script><style scoped></style>

插槽_具名插槽

父组件

<template><div><NavComponent><template v-slot:left><button>返回</button></template><template v-slot:center>首页</template><template v-slot:right><a href="#" >登录</a></template></NavComponent><NavComponent><template v-slot:[position]><button>返回</button></template></NavComponent><button @click="position = 'left'">左边</button><button @click="position = 'center'">中间</button><button @click="position = 'right'">右边</button></div>
</template><script>import NavComponent from './NavComponent.vue';export default {components:{NavComponent},data(){return {position:'left'}}}
</script><style scoped></style>

**子组件 NavComponent.vue **

<template><div><div style="display: flex;flex-direction: row;height: 100px;"><div class="left"> <slot name="left">左边</slot>   </div><div class="center">  <slot name="center">中间</slot> </div><div class="right"><slot name="right">右边</slot></div></div></div>
</template><script>export default {}
</script><style scoped>.left{width:30%;background-color: aqua;}.center{width: 40%;background-color: bisque;}.right{width: 30%;background-color: blueviolet;}
</style>

组件插槽_作用域插槽

父组件

<template><div><NavComponet :nav_list="nav_list"><template v-slot:default="porps_val">{{ porps_val.item }}---{{ porps_val.abc }}</template></NavComponet><!--  --><hr><NavComponet :nav_list="nav_list"><template #default="porps_val"><a href="#">{{ porps_val.item }}---{{ porps_val.abc }}</a></template></NavComponet></div>
</template><script>import NavComponet from './NavComponet.vue'export default {components:{NavComponet},data(){return {nav_list:[{id:1,title:'标题1'},{id:1,title:'标题2'},{id:1,title:'标题3'},]}}}
</script><style scoped></style>

子组件 NavComponet.vue

<template><div><div class="nav"><div v-for="(item,index) in nav_list" :key="index" class="nav_item"><div>{{ item.title }}</div><slot :item="item.title" abc="cba"><div>{{ item.title }}</div></slot></div></div></div>
</template><script>export default {props:{nav_list:{type:Array,default:()=>{return [{id:1,title:'衣服'},{id:1,title:'食物'},{id:1,title:'玩具'},];}}},data(){return {}}}
</script><style scoped>.nav{display: flex;flex-direction: row;}.nav_item{flex:1;}
</style>

Provide和Inject

App.vue

<template><div class="app"><home-component></home-component><h2>app:{{ message }}</h2><button @click="message = 'hello world'">改变message</button></div>
</template><script>import { computed  } from 'vue'import HomeComponent from './HomeComponent.vue'export default {components:{HomeComponent},data(){return {message:"Hello App"}},provide(){return {name:"why",age:18,message:computed(()=>{return this.message}) }}}
</script><style scoped></style>

**子组件 HomeBanner.vue **

<template><div><h2>HomeBanner:{{ name }} - {{ age }} - {{ message }}</h2></div>
</template><script>export default {inject:["name","age","message"]}
</script><style scoped></style>

孙组件 HomeComponent.vue

<template><div><home-banner></home-banner></div>
</template><script>import HomeBanner from './HomeBanner.vue';export default {components:{HomeBanner},data(){return {}}}
</script><style scoped></style>

事件总线的使用

App.vue

<template><div class="app"><!-- 安装状态管理库 npm install hy-event-store --><!-- Mitt事件状态(略) --><HomeCon></HomeCon>  <h2>{{ message }}</h2><button @click="show_cate_gory = !show_cate_gory">是否显示cate_gory</button><cate-gory v-if="show_cate_gory"></cate-gory></div>
</template><script>import eventBus from './utils/event.bus';import HomeCon from './HomeCon.vue'import CateGory from './CateGory.vue'export default {components:{HomeCon,CateGory},data(){return {message:'hello vue',show_cate_gory:true}},created(){// 事件监听eventBus.on("whyEvent",(name,age,height)=>{console.log("whyEvent事件在app中的监听",name,age,height)this.message = `name:${name},age:${age},height:${height}`})}}
</script><style scoped></style>

** 子组件 CateGory.vue**

<template><div><h2>Category</h2></div>
</template><script>import eventBus from './utils/event.bus.js'export default {methods:{whyEventHandler(){console.log("whyEvent在category中监听")}},created(){eventBus.on("whyEvent",this.whyEventHandler)},unmounted(){console.log("category umounted")eventBus.off("whyEvent",this.whyEventHandler)}}
</script><style scoped></style>

**子组件 HomeBanner.vue **

<template><div><button @click="bannerBtnClick">banner按钮</button></div>
</template><script>import eventBus  from './utils/event.bus';export default {methods:{bannerBtnClick(){console.log("bannerBtnClick")eventBus.emit("whyEvent","why",18,1.88)}}}
</script><style scoped></style>

** 子组件 HomeCon.vue**

<template><div><home-banner></home-banner></div>
</template><script>import HomeBanner from './HomeBanner.vue';export default {components:{HomeBanner},data(){return {}}}
</script><style scoped></style>

事件总线 event.bus.js

import { HYEventBus } from "hy-event-store"const eventBus = new HYEventBus()export default eventBus

生命周期函数演练

App.vue

<template><div><h2>{{ message }}---{{ counter }}</h2><button @click="message = 'hello world'" >修改message</button><button @click="counter++">+1</button><button @click="showHome = !showHome">隐藏home</button><home-com v-if="showHome"></home-com></div>
</template><script>import HomeCom from "./HomeCom.vue"export default {components:{HomeCom},data(){return {message:'hello vue',counter:1,showHome:true}},// 1.组件创建之前beforeCreate(){console.log("beforeCreate")},// 2.组件被创建完成created(){console.log("组件被创建完成:created")console.log("1.发送网络请求,请求数据")console.log("2.监听eventbus事件")console.log("3.监听watch数据")},// 3. 组件template准备被挂在beforeMount(){console.log("beforeMount")},// 4.组件template被挂载,虚拟dom=》真实dommounted(){console.log("mounted")console.log("1.获取DOM")console.log("2.使用DOM")},// 5.数据发生改变// 5.1 准备更新DOMbeforeUpdate(){console.log("beforeUpdate")},// 5.2 更新DOMupdated(){console.log("updated")},// 6.卸载Vnode-》DOM原生// 6.1 卸载之前beforeUnmount(){console.log("beforeUnmount")},// 6.2 DOM元素被卸载完成unmounted(){console.log("unmounted")}}
</script><style scoped></style>

子组件 HomeCom.vue

<template><div>Home</div>
</template><script>export default {unmounted(){console.log("unmounted home")},beforeUnmount(){console.log("beforeUnmout home")}}
</script><style scoped></style>

ref获取元素组件

App.vue

<template><div><h2 ref="title" class="title" :style="{color:titleColor}">{{ message }}</h2><button ref="btn" @click="changeTitle">修改title</button><BannerCom ref="banner"></BannerCom><BannerCom ref="banner"></BannerCom><BannerCom ref="banner"></BannerCom><BannerCom ref="banner"></BannerCom><BannerCom ref="banner"></BannerCom></div>
</template><script>import BannerCom from './BannerCom.vue';export default {components:{BannerCom},data(){return {message:"hello world",titleColor:"red"}},methods:{changeTitle(){// 1.不要主动去获取DOM,并且修改DOM内容this.message = "你好啊,世界"this.titleColor = "blue"// 2.获取h2/button元素console.log(this.$refs.title)console.log(this.$refs.btn)// 3.获取banner组件:组件实例console.log(this.$refs.banner)// 3.1在父组件中可以主动的调用子组件的方法this.$refs.banner.bannerClick()// 3.2 获取banner组件实例,获取banner中的元素console.log(this.$refs.banner.$el)// 3.3 如果banner template是多个根,拿到的是一个node节点console.log(this.$refs.banner.$el.nextElementSibling)// 第二个node节点console.log(this.$refs.banner.$el.previousElementSibling)// 4.组件实例了解console.log(this.$parent); // 父组件console.log(this.$root); //根组件}}} 
</script><style scoped></style>

**子组件 BannerCom.vue **

<template><div class="banner">Banner</div><div class="banner2"></div>
</template><script>export default {methods:{bannerClick(){console.log('bannerClick')}}}
</script><style scoped></style>

内置组件的使用

App.vue

<template><div><button v-for="(item,index) in tab_arr" :style="default_tab == item ? 'color:red;' : ''" :key="index" @click="show_tab(item)">{{ item }}</button><!-- 第一中方法 --><!-- <div v-if="default_tab=='home'"><HomeCom></HomeCom></div><div v-if="default_tab=='about'"><AboutCom></AboutCom></div><div v-if="default_tab=='category'"><CategoryCom></CategoryCom></div> --><!-- 第二种方式 --><component name="kb" age="20" @homebtn="homebtn" :is="default_tab"></component></div>
</template><script>import HomeCom from './views/HomeCom.vue'import AboutCom from './views/AboutCom.vue'import CategoryCom from './views/CategoryCom.vue'export default {components:{HomeCom,AboutCom,CategoryCom},data(){return {tab_arr:['HomeCom','AboutCom','CategoryCom'],default_tab:'HomeCom'}},methods:{show_tab(item){this.default_tab = item},homebtn(eve){console.log('homebtn',eve)}}}
</script><style scoped></style>

** 子组件 AboutCom.vue**

<template><div>about组件</div>
</template><script>export default {}
</script><style scoped></style>

子组件 CategoryCom.vue

<template><div>category组件</div>
</template><script>export default {}
</script><style scoped></style>

子组件 HomeCom.vue

<template><div>home组件{{ name }} --- {{ age }}<button @click="homebtn">homebtn</button></div>
</template><script>export default {data(){return {}},props:{name:{type:String,default:'why'},age:{type:String,default:'18'}},emits:['homebtn'],methods:{homebtn(){this.$emit('homebtn','home')}}}
</script><style scoped></style>

Keep-Alive的使用-分包

App.vue

<template><div><button v-for="(item,index) in tab_arr" :style="default_tab == item ? 'color:red;' : ''" :key="index" @click="show_tab(item)">{{ item }}</button><!-- 第一中方法 --><!-- <div v-if="default_tab=='home'"><HomeCom></HomeCom></div><div v-if="default_tab=='about'"><AboutCom></AboutCom></div><div v-if="default_tab=='category'"><CategoryCom></CategoryCom></div> --><!-- 第二种方式 --><KeepAlive include="HomeCom,AboutCom"><component :is="default_tab"></component></KeepAlive></div>
</template><script>
import { defineAsyncComponent } from 'vue'import HomeCom from './views/HomeCom.vue'import AboutCom from './views/AboutCom.vue'
//  import CategoryCom from './views/CategoryCom.vue'const AsyncCategory = defineAsyncComponent(()=>import("./views/CategoryCom.vue"))export default {components:{HomeCom,AboutCom,CategoryCom:AsyncCategory},data(){return {tab_arr:['HomeCom','AboutCom','CategoryCom'],default_tab:'HomeCom'}},methods:{show_tab(item){this.default_tab = item},homebtn(eve){console.log('homebtn',eve)}}}
</script><style scoped></style>

子组件 AboutCom.vue

<template><div>about组件</div>
</template><script>export default {name:"AboutCom",created(){console.log('about created')},unmounted(){console.log('about unmounted')},}
</script><style scoped></style>

**子组件 CategoryCom.vue **

<template><div>category组件</div>
</template><script>export default {created(){console.log('category created')},unmounted(){console.log('category unmounted')},}
</script><style scoped></style>

子组件 HomeCom.vue

<template><div>home组件<div>计数:{{ counter }}</div><button @click="jia">加1</button></div>
</template><script>export default {name:"HomeCom",data(){return {counter:0}},created(){console.log('home created')},unmounted(){console.log('home unmounted')},// 对于保持keep-alive组件,监听有没有进行切换// keep-alive组件进入活跃状态activated(){console.log('home activated')},deactivated(){console.log('home deactivated')},  methods:{jia:function(){this.counter++;}}}
</script><style scoped></style>

组件的v-model

App.vue

<template><div class="app"><!-- 1.input v-model --><!-- <input type="text" v-model="message"> --><!-- <input type="text" :value="message" @input="message = $event.target.value"> --><!-- <CounterCom :modelValue="appCounter" @update:modelValue="appCounter = $event"></CounterCom> --><!-- <CounterCom v-model="appCounter"></CounterCom> --><CounterCom2 v-model:counter="appCounter" v-model:why="why"></CounterCom2></div>
</template><script>import CounterCom2 from './CounterCom2.vue'export default {components:{CounterCom2},data(){return {message:'hello',appCounter:"100",why:'coderwhy'}}}
</script><style scoped></style>

**子组件 CounterCom.vue **

<template><div>counter<div>modelValue:{{ modelValue }}</div><button @click="changeCounter">修改counter</button></div>
</template><script>export default {props:{modelValue:{type:String,default:''}},emits:["update:modelValue"],methods:{changeCounter(){this.$emit("update:modelValue",'999999')}}}
</script><style scoped></style>

子组件 CounterCom2.vue

<template><div><div>counter:{{ counter }}</div><button @click="changeCounter">修改counter</button><div>why:{{ why }}</div><button @click="changeWhy">修改why的值</button></div>
</template><script>export default {props:{counter:{type:String,default:''},why:{type:String,default:''}},emits:["update:counter","update:why"],methods:{changeCounter(){ this.$emit("update:counter",'999999')},changeWhy(){this.$emit("update:why",'kobi')}}}
</script><style scoped></style>

组件的混入Mixin

message-mixin.js

export default {data(){return {message:"Hello World"}},created(){console.log("message:",this.message)}
}

**App.vue **

<template><div><HomeCon></HomeCon><AboutCon></AboutCon><CatetoryCon></CatetoryCon></div>
</template><script>import HomeCon from './views/HomeCon.vue'import AboutCon from './views/AboutCon.vue'import CatetoryCon from './views/CatetoryCon.vue'export default {components:{HomeCon,AboutCon,CatetoryCon}}
</script><style scoped></style>

子组件 AboutCon.vue

<template><div><h2>AboutCon组件</h2></div>
</template><script>
import messageMixin from  '../mixins/message-mixin'export default {mixins:[messageMixin]}
</script><style scoped></style>

子组件 CatetoryCon.vue

<template><div><h2>CatetoryCon组件</h2></div>
</template><script>
import messageMixin from  '../mixins/message-mixin'export default {mixins:[messageMixin]}
</script><style scoped></style>

子组件 HomeCon.vue

<template><div><h2>HomeCon组件</h2></div>
</template><script>
import messageMixin from  '../mixins/message-mixin'export default {mixins:[messageMixin]}
</script><style scoped></style>

感谢观看,我们下次再见

这篇关于Vue3的手脚架使用和组件父子间通信-插槽(Options API)学习笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/354165

相关文章

SpringBoot结合Knife4j进行API分组授权管理配置详解

《SpringBoot结合Knife4j进行API分组授权管理配置详解》在现代的微服务架构中,API文档和授权管理是不可或缺的一部分,本文将介绍如何在SpringBoot应用中集成Knife4j,并进... 目录环境准备配置 Swagger配置 Swagger OpenAPI自定义 Swagger UI 底

setsid 命令工作原理和使用案例介绍

《setsid命令工作原理和使用案例介绍》setsid命令在Linux中创建独立会话,使进程脱离终端运行,适用于守护进程和后台任务,通过重定向输出和确保权限,可有效管理长时间运行的进程,本文给大家介... 目录setsid 命令介绍和使用案例基本介绍基本语法主要特点命令参数使用案例1. 在后台运行命令2.

基于Python Playwright进行前端性能测试的脚本实现

《基于PythonPlaywright进行前端性能测试的脚本实现》在当今Web应用开发中,性能优化是提升用户体验的关键因素之一,本文将介绍如何使用Playwright构建一个自动化性能测试工具,希望... 目录引言工具概述整体架构核心实现解析1. 浏览器初始化2. 性能数据收集3. 资源分析4. 关键性能指

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R

使用Python的requests库调用API接口的详细步骤

《使用Python的requests库调用API接口的详细步骤》使用Python的requests库调用API接口是开发中最常用的方式之一,它简化了HTTP请求的处理流程,以下是详细步骤和实战示例,涵... 目录一、准备工作:安装 requests 库二、基本调用流程(以 RESTful API 为例)1.

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

Python yield与yield from的简单使用方式

《Pythonyield与yieldfrom的简单使用方式》生成器通过yield定义,可在处理I/O时暂停执行并返回部分结果,待其他任务完成后继续,yieldfrom用于将一个生成器的值传递给另一... 目录python yield与yield from的使用代码结构总结Python yield与yield

Go语言使用select监听多个channel的示例详解

《Go语言使用select监听多个channel的示例详解》本文将聚焦Go并发中的一个强力工具,select,这篇文章将通过实际案例学习如何优雅地监听多个Channel,实现多任务处理、超时控制和非阻... 目录一、前言:为什么要使用select二、实战目标三、案例代码:监听两个任务结果和超时四、运行示例五

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

Java使用Thumbnailator库实现图片处理与压缩功能

《Java使用Thumbnailator库实现图片处理与压缩功能》Thumbnailator是高性能Java图像处理库,支持缩放、旋转、水印添加、裁剪及格式转换,提供易用API和性能优化,适合Web应... 目录1. 图片处理库Thumbnailator介绍2. 基本和指定大小图片缩放功能2.1 图片缩放的