npm install @vue/cli -g
npm update @vue/cli -g
通过脚手架创建项目
vue create 01_product_demo
父组件
<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)">+1button>
<button @click="jia(5)">+5button>
<button @click="jia(10)">+10button>
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)">-1button>
<button @click="jian(5)">-5button>
<button @click="jian(10)">-10button>
div>
div>
template>
<script>
export default {
methods:{
jian(data){
this.$emit("jian",data);
}
}
}
script>
<style scoped>
style>
父组件
<template>
<div>
<TitleComponents title="标题" desc="描述描述描述描述描述">TitleComponents>
<TitleComponents title="标题" desc="描述描述描述描述描述">
<button>按钮button>
TitleComponents>
<TitleComponents title="标题" desc="描述描述描述描述描述">
<a href="https://www.baidu.com">百度一下a>
TitleComponents>
<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>
<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>
App.vue
<template>
<div class="app">
<home-component>home-component>
<h2>app:{{ message }}h2>
<button @click="message = 'hello world'">改变messagebutton>
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">
<HomeCon>HomeCon>
<h2>{{ message }}h2>
<button @click="show_cate_gory = !show_cate_gory">是否显示cate_gorybutton>
<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>Categoryh2>
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'" >修改messagebutton>
<button @click="counter++">+1button>
<button @click="showHome = !showHome">隐藏homebutton>
<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=》真实dom
mounted(){
console.log("mounted")
console.log("1.获取DOM")
console.log("2.使用DOM")
},
// 5.数据发生改变
// 5.1 准备更新DOM
beforeUpdate(){
console.log("beforeUpdate")
},
// 5.2 更新DOM
updated(){
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>
App.vue
<template>
<div>
<h2 ref="title" class="title" :style="{color:titleColor}">{{ message }}h2>
<button ref="btn" @click="changeTitle">修改titlebutton>
<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>
<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">homebtnbutton>
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>
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>
<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">加1button>
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>
App.vue
<template>
<div class="app">
<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">修改counterbutton>
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">修改counterbutton>
<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>
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>
感谢观看,我们下次再见