Vue3的手脚架使用和组件父子间通信

编程入门 行业动态 更新时间:2024-10-24 04:32:28

Vue3的手<a href=https://www.elefans.com/category/jswz/34/1737853.html style=脚架使用和组件父子间通信"/>

Vue3的手脚架使用和组件父子间通信

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="">百度一下</a></TitleComponents><!-- 3.插入image --><TitleComponents title="标题" desc="描述描述描述描述描述"><img src="=http%3A%2F%2Fpics6.baidu%2Ffeed%2F34fae6cd7b899e512cb62692d10fdf3ec9950db4.jpeg%40f_auto%3Ftoken%3D8ce9dbae74003846c318068640c41183&refer=http%3A%2F%2Fwww.baidu&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的手脚架使用和组件父子间通信

本文发布于:2023-11-16 11:17:27,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1619598.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:脚架   父子   组件   通信

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!