vue学习笔记

结合目录,点击阅读

文章目录

案例1:第一行vue代码

App.vue引入Person.vue

typescript 复制代码
<template>
  <div class="app">
    <h1>你好啊!</h1>
    <Person/>
  </div>
</template>

<script lang="ts">
import Person from './Person.vue'

export default {
  name: 'App',
  components: {
    Person
  }
}
</script>

Person.vue

typescript 复制代码
<template>
  <div class="person">
  
      <h2>姓名:{{a}}</h2>

  </div>

</template>


<script lang="ts" setup name="Person5467">
  let a = 666
</script>

<style scoped>
  .person {
      background-color: skyblue;
      box-shadow: 0 0 10px;
      border-radius: 10px;
      padding: 20px;
  }
</style>

案例:改变变量的值

typescript 复制代码
 const age = ref(18)
 age.value = 21

案例:改变对象属性值

html遍历游戏列表

html 复制代码
<ul>
    <li v-for="g in games" :key="g.id">
        {{g.name}}
    </li>
</ul>
typescript 复制代码
let car = reactive({brand:'奔驰',price:100})
 let games = reactive([
     {id:'001',name:'王者荣耀'},
     {id:'002',name:'原神'},
     {id:'003',name:'三国志'}
     
 ])
function changePrice() {
    car.price += 10
    console.log(car.price)
}
function changeFirstGame() {
    games[0].name = "三国志123"
}

案例:toRefs进行解包

typescript 复制代码
let person = reactive({
     name:'张三',
     age:18
 })

 //toRef与toRefs都是将响应式对象进行解包
 let {name,age} = toRefs(person)

案例:给名字首字母大写

html 复制代码
 全名: <span>{{ fullname }}</span><br> 
 <button @click="changeFullName">将全名改</button>

ts代码

html 复制代码
let fullname = computed({
      get() {
          return firstname.value.slice(0,1).toUpperCase() + firstname.value.slice(1) + "-" + lastname.value

      },
      set(val) {
          const[str1,str2] = val.split('-')
          firstname.value = str1
          lastname.value = str2

      }
  })

案例:监视变量值的变化

typescript 复制代码
let sum = ref(0)
function changeSum() {
     sum.value += 1 
}

watch(sum,(newValue,oldValue)=>{
 console.log('sum变化了',newValue,oldValue)
})

案例:监视对象属性值的变化

typescript 复制代码
let person = ref({
      name:'张三',
      age:18
 })
watch(person,(newValue,oldValue)=>{
   console.log('person变化了',newValue,oldValue)
},{deep:true})

案例:监视reactive对象属性值的变化

typescript 复制代码
let person = reactive({
    name:'张三',
    age:18
})
let obj = reactive({
    a :{
        b:{
            c:555
        }
    }
})
watch(person,(newValue,oldValue)=>{
    console.log('person变化了',newValue,oldValue)
})
watch(obj,(newValue,oldValue)=>{
    console.log('Obj变化了',newValue,oldValue)
})

案例:监视reactive对象定义的某个属性值

typescript 复制代码
let person = reactive({
     name:'张三',
     age:31,
     model:'汽车',
     car:{
         c1:'奔驰',
         c2:'宝马'
     }
})
watch(()=>person.name,(newValue,oldValue)=>{
    console.log(newValue,oldValue)
})

案例:监视reactive对象定义的多个属性值

typescript 复制代码
let person = reactive({
     name:'张三',
     age:31,
     model:'汽车',
     car:{
         c1:'奔驰',
         c2:'宝马'
     }
})
watch(()=>person.name,(newValue,oldValue)=>{
   console.log(newValue,oldValue)
})
watch([()=>person.name,()=>person.car.c1],(newValue,oldValue)=>{
   console.log('person变化了',oldValue,newValue)
},{deep:true})

案例:watchEffect监视ref变量的值

typescript 复制代码
let tempature = ref(0)
let height = ref(10)
watchEffect(()=>{
    if(tempature.value > 20 || height.value > 30 ){
        console.log("aa")
    }
})

案例:defineExpose通信

typescript 复制代码
  <Person ref="ren"/>
typescript 复制代码
<script lang="ts" setup name="App">
	import {ref} from 'vue'
	//ts或者js
	import Person from './components/Person.vue'
	let title2 = ref()
	let ren = ref()
	
	function showLog(){
	  console.log(ren.value)
	}
</script>
typescript 复制代码
<script lang="ts" setup name="Person5467">
	import {ref,defineExpose} from 'vue'
	let title2 = ref()
	let a = ref(0)
	let b = ref(0)
	let c = ref(0)
	function showLog() {
	 console.log("Person.Log")
	}
	defineExpose({a,b,c})

</script>

案例:组件通信

typescript 复制代码
<script lang="ts" setup name="App">
import {reactive} from 'vue'
//ts或者js
let x = 4
import {type Persons} from '@/types'
import Person from './components/Person.vue'
let personList = reactive<Persons>([
  {id:'001',name:'张三',age:13},
  {id:'002',name:'李四',age:20},
  {id:'003',name:'王五',age:22},
])

</script>
typescript 复制代码
<script lang="ts" setup name="Person5467">
import type { Persons } from '@/types';
import { defineProps,withDefaults } from 'vue';
//   接收list
//   defineProps(['list'])
//接收list+限制类型    
// defineProps<{list:Persons}>()
//接收list+限制类型+限制必要性+指定默认值
withDefaults(defineProps<{list?:Persons}>(),{
  list:()=>[{id:'1',name:'张三',age:12}]
})
</script>

案例:状态与钩子函数

typescript 复制代码
<script lang="ts" setup name="Person5467">
import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref } from 'vue';

 let sum = ref(0)
 function add(){
     sum.value += 1
 }
 //挂载前
 onBeforeMount(()=>{
     console.log('挂载前')
 })
 //挂载后
 onMounted(()=>{
     console.log("已挂载")
 })
 //更新前
 onBeforeUpdate(()=>{
     console.log("更新前")
 })
 //更新完毕
 onUpdated(()=>{
     console.log("更新完毕")
 })
 //卸载前
 onBeforeUnmount(()=>{
     console.log("卸载前")
 })
 
 //卸载完毕
 onUnmounted(()=>{
     console.log("卸载完毕")
 })
</script>

案例:Component声明与使用

ts文件

typescript 复制代码
import { ref } from "vue"

export default function (){
    let sum =ref(0)
    function add(){
        sum.value += 1
    }
    return {sum,add}
}

vue文件组件加载

typescript 复制代码
<template>
    <Person/>
</template>

<script lang="ts">
    import Person from "./components/Person.vue"
    export default {
        name:'App',
        components:{Person} //注册组件
    }
</script>

vue文件:ts文件加载

typescript 复制代码
<script lang="ts" setup name="Person5467">
    import useDog from '@/hooks/useDog'
    import useSum from '@/hooks/useSum'
    const {sum,add} = useSum()
    const {dogList,getDog} = useDog()
</script>

案例:创建路由器

typescript 复制代码
import {createRouter, createWebHistory} from 'vue-router'
import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
//第二部:创建路由器
const router = createRouter({
    history:createWebHistory(),
    routes:[
        {
            path:'/home',
            component:Home
        },
        {
            path:'/about',
            component:About
        },
        {
            path:'/news',
            component:News
        },
    ]
})
export default router
typescript 复制代码
<template>
  <div class="app">
      <h2 class="title">Vue路由测试</h2>
      <div class="navigate">
          <RouterLink  to="/home" active-class="active">首页</RouterLink>
          <RouterLink to="/news" active-class="active">新闻</RouterLink>
          <RouterLink  :to="{path:'/about'}" active-class="active">关于</RouterLink>
      </div>
      <div class="main-content">
          <RouterView></RouterView>
      </div>
  </div>
</template>

案例:创建子路由

typescript 复制代码
import {createRouter, createWebHistory} from 'vue-router'


import Home from '@/pages/Home.vue'
import News from '@/pages/News.vue'
import About from '@/pages/About.vue'
import Detail from '@/pages/Detail.vue'
//第二部:创建路由器
const router = createRouter({
    history:createWebHistory(),
    routes:[
        {
            path:'/home',
            component:Home
        },
        {
            path:'/about',
            component:About
        },
        {
            path:'/news',
            component:News,
            children:[
                {
                    path:'detail',
                    component:Detail
                }
            ]
        },
    ]
})
export default router

案例:路由传参

typescript 复制代码
<RouterLink 
:to = "{
    name:'detail',
    params:{
        id:news.id,
        title:news.title,
        content:news.content,
    }
}">{{ news.title }}</RouterLink>

案例:路由props

typescript 复制代码
<script setup lang="ts" name="News">
import { useRoute } from 'vue-router';

   defineProps(['id','title','content'])
</script>

案例:路由重定向

typescript 复制代码
const router = createRouter({
  history:createWebHistory(),
  routes:[
      {
          path:'/home',
          component:Home
      },
      {
          path:'/about',
          component:About
      },
      {
          path:'/news',
          component:News,
          children:[
              {
                  name:'detail',
                  path:'detail/:id/:title/:content',
                  component:Detail,
                  //第一种写法,将路由收到的所有params参数作为props传给路由组件

                  props:true,
                  //第二种写法:可以自己决定讲什么作为参数
                  // props(to) {
                  //     console.log(to.query.id,to.query.title,to.query.content)
                  //     return to.query
                  // },
              }
          ]
      },
      {
          path:'/',
          redirect:'/home'
      }
  ]
})

案例:store

ts文件

typescript 复制代码
import { defineStore } from "pinia"

export const useCountStore = defineStore('count',{
   state() {
       return {
           sum:6
       }
   }
})
typescript 复制代码
<script setup lang="ts" name="Count">
import { ref } from 'vue';
import { useCountStore } from '@/store/count'
const countStore = useCountStore()
//reactive 里面包含ref,就不需要拆包value
console.log('@@@',countStore.sum)
   let n = ref(1)
   function add() {

   }
   function minus() {

   }
</script>

案例:数据修改

typescript 复制代码
<script setup lang="ts" name="Count">
import { ref } from 'vue';
import { useCountStore } from '@/store/count'
const countStore = useCountStore()
//reactive 里面包含ref,就不需要拆包value
console.log('@@@',countStore.sum)
    let n = ref(1)
    function add() {
        // countStore.sum += 1
        //第二种改变方式
        // countStore.$patch({
        //     sum:888,
        //     school:'尚硅谷',
        //     address:'北京'
        // })
        //第三宗
        countStore.increment(n.value)
    }
</script>
typescript 复制代码
import { defineStore } from "pinia"

export const useCountStore = defineStore('count',{
   actions:{
       increment(value: number){
           console.log("increment被调用了",value)
           this.sum += value
       }
   },
   state() {
       return {
           sum:6,
           school:'atguigu',
           address:'hong'
       }
   }
})

案例:pina中storeToRefs

typescript 复制代码
<script setup lang="ts" name="Count">
import { ref } from 'vue';
import { useCountStore } from '@/store/count'
import { storeToRefs } from 'pinia';
const countStore = useCountStore()
//reactive 里面包含ref,就不需要拆包value
console.log('@@@',countStore.sum)
let n = ref(1)
const {school,address,sum} = storeToRefs(countStore)
function add() {
    countStore.increment(n.value)
}

</script>
typescript 复制代码
import { defineStore } from "pinia"
export const useCountStore = defineStore('count',{
  actions:{
      increment(value: number){
          console.log("increment被调用了",value)
          this.sum += value
      }
  },
  state() {
      return {
          sum:6,
          school:'atguigu',
          address:'hong'
      }
  }
})

案例:pinia进行数据改变

typescript 复制代码
import { defineStore } from "pinia"

export const useCountStore = defineStore('count',{
    actions:{
        increment(value: number){
            console.log("increment被调用了",value)
            this.sum += value
        }
    },
    state() {
        return {
            sum:6,
            school:'atguigu',
            address:'hong'
        }
    },
    getters:{
        bigSum:state =>state.sum * 10,
        upperSchool():string{
            return this.school.toUpperCase()
        }
    }

})

案例:defineProps

Father.vue

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <h4>父亲的玩具:{{ car }}</h4>
        <h4>儿子的玩具:{{ toy }}</h4>
        <Child :car="car" :sendToy="getToy"/>
    </div>
</template>

<script setup lang="ts" name="Father">
    import Child from './Child.vue'
    import {ref} from 'vue'
    let car = ref('帕拉梅拉')
    let toy = ref('')
    function getToy(v:string){
        toy.value = v
    }
</script>
<style scoped>
    .father {
        background-color: rgb(165,164,164);
        padding: 20px;
        border-radius: 10px;
    }
</style>

Child.vue

typescript 复制代码
<template>
    <div class="child">
        <h3>子组件</h3>
        <h4>儿子的玩具:{{   toy }}</h4>
        <h4>父亲的玩具:{{ car }}</h4>
        <button @click="sendToy(toy)">玩具给父亲</button>
    </div>
</template>

<script setup lang="ts" name="Child">
   import {ref} from 'vue'
    let toy = ref('奥特玛')
    defineProps(['car','sendToy'])
    function send() {

    }
</script>

<style scoped>
    .child {
        background-color: skyblue;
        padding:10px;
        box-shadow: 0 0 10px black;
        border-radius: 10px;
    }
</style>

案例:shallowRef

typescript 复制代码
<template>
   <div class="app">
    <h3>求和为:{{ sum }}</h3>
    <h3>名字为:{{ person.name }}</h3>
    <h3>年龄为:{{ person.age }}</h3>
    <h3>车子为{{car}}</h3>
    
    <button @click="changeSum">sum+1</button>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changePerson">修改整个人</button>
    <span>|</span>
    <button @click="changeBrand">修改品牌</button>
    <button @click="changeColor">修改品牌</button>
    <button @click="changeEngine">修改品牌</button>
   </div>

</template>

<script lang="ts" setup name="App">
    import {reactive, ref, shallowReactive, shallowRef} from 'vue'
    //shallowRef只关心浅层次,也就是第一层**.value
    //实战中更关心整体替换,下面是一串官方的话
    //通过使用shallowRef()和shallowReactive()来绕开深度相应,
    //浅层式api创建的状态只在其顶层是响应式的,对所有深层的对象不会做任何处理
    //避开了对每一个内部属性做响应式所带来的性能成本,这使得
    //属性的访问变得更快,可提升性能
    let sum = shallowRef(0)
    let person = shallowRef({
        name:'张三',
        age:18
    })
    let car = shallowReactive({
        brand:'帕拉梅拉',
        options:{
            engine:'v8',
            color:'purple'
        }
    })
    function changeSum(){
        sum.value += 1
    }
    function changeName(){
        person.value.name += '李四'
    }
    function changeAge(){
        person.value.age += 1
    }
    function changePerson(){
        person.value.age += 3
        person.value.name += '王五'
        
    }
    function changeBrand(){
        car.brand = "法拉利"
    }
    function changeColor(){
        car.options.color = "blue"
    }
    function changeEngine(){
        car.options.engine = "v12"
    }
</script>

<style scoped>
    .app{
        background-color: #ddd;
        border-radius: 10px;
        box-shadow: 0 0 10px;
        padding: 10px;
    }
</style>

案例:readOnly与shallowReadOnly

typescript 复制代码
<template>
   <div class="app">
        <h3>当前sum1为:{{ sum1 }}</h3>
        <h3>当前sum2为:{{ sum2 }}</h3>
        <h3>当前车为{{car1}}</h3>
        <h3>当前车为{{car2}}</h3>
        <button @click="changeSum1">点我sum1+1</button>
        <button @click="changeSum2">点我sum2+1</button>
        <button @click="changeBrand">修改品牌</button>
        <button @click="changeColor">修改颜色</button>
        <button @click="changePrice">修改价格</button>
    </div>

</template>

<script lang="ts" setup name="App">
    import {ref,readonly,reactive, shallowReadonly} from 'vue';
    let sum1 = ref(0)
    let sum2 = readonly(sum1) //深只读副本
    let car1 = reactive({
        brand:'奔驰',
        options:{
            color:'红色',
            price:100
        }
    })
    let car2 = shallowReadonly(car1) //只用于对象的顶层属性
    function changeSum1(){
        sum1.value += 1
    }
    function changeSum2() {
        sum2.value += 1
    }
    function changeBrand() {
        car2.brand = '帕拉梅拉'
    }
    function changeColor() {
        car2.options.color = 'purple'   
    }
    function changePrice() {
        car2.options.price = 200
    }
</script>

<style scoped>
    .app{
        background-color: #ddd;
        border-radius: 10px;
        box-shadow: 0 0 10px;
        padding: 10px;
    }
</style>

案例:markRaw与toRaw

typescript 复制代码
<template>
<!-- toRaw:用于获取一个响应式对象的原始对象, -->
<!-- toRaw返回的对象不再是响应式的,不会触发视图更新 -->
<!-- markRow:标记一个对象,使其永远不会变成响应式的 -->
<h2>姓名:{{ person2.name }}</h2>
<h2>年龄:{{ person2.age }}</h2>
<h2>一个车子{{ car2 }}</h2>
<button @click="person2.age += 1">修改年龄</button>
<button @click="changePerson(person2)">修改整个人</button>
<button @click="car2.price += 10">修改车的价格</button>
</template>

<script lang="ts" setup name="App">
    import {markRaw, reactive,toRaw} from 'vue'

    let person2 = reactive({
        name:'tony',
        age:17
    })
    let rawPerson = toRaw(person2)
    function changePerson(p){
        p.age +=1 
        p.name = 'tom'
    }
    let car = markRaw({brand:'帕拉梅拉',price:100})
    let car2 = reactive(car)

</script>

<style scoped>
    .app{
        background-color: #ddd;
        border-radius: 10px;
        box-shadow: 0 0 10px;
        padding: 10px;
    }
</style>

案例:customRef

自定义ref useMsg.ts

typescript 复制代码
import { customRef } from 'vue';

export default function(initValue:string,delay:number){
   let timer:number
   let msg = customRef((track,trigger)=>{
    return {
        get() {
            track()
            return initValue
        },
        set(value){
           clearTimeout(timer)
           timer = setTimeout(()=>{
               console.log('set',value)
               initValue = value
               trigger()
           },delay)
        }
    }
   })
   return {msg}
}

.vue

typescript 复制代码
<template>
    <h3>我想要的:{{ msg }}</h3>
    <input type="text" v-model="msg">

</template>

<script lang="ts" setup name="App">
import useMsg from './useMsg';

    let {msg} = useMsg('你好',2000)

</script>

<style scoped>
    .app{
        background-color: #ddd;
        border-radius: 10px;
        box-shadow: 0 0 10px;
        padding: 10px;
    }
</style>

案例:telePort

Modal.vue

typescript 复制代码
<template>
    <button @click="isShow=true">暂时弹窗</button>
    <div class="modal" v-show="isShow">
       <h2>我是标题</h2>
        <p>我是内容</p>
        <button>我是弹窗</button>
    </div>
    <!-- 创建一个自定义的ref,并对其依赖项追踪和更新触发进行逻辑控制 -->
</template>

<script lang="ts" setup name="Modal">
import { ref } from 'vue';

    let isShow = ref(false)

</script>

<style scoped>
    .modal{
        width: 200px;
        height: 150px;
        background-color: skyblue;
        border-radius: 10px;
        box-shadow: 0 0 10px;
        padding: 5px;
        text-align: center;
        position: fixed;
        left:50%;
        top:20px;
        margin-left: -100px;
    }
</style>

App.vue

typescript 复制代码
<template>
    <div class="outer">
        <h2>我是app组件</h2>
        <img src="./tmp.png" alt="">
        <br>
        <Modal />
    </div>

</template>

<script lang="ts" setup name="App">

    import Modal from './Modal.vue'
</script>

<style scoped>
.outer {
    background-color: #ddd;
    border-radius: 10px;
    padding: 5px;
    box-shadow: 0 0 10px;
}
img {
    width: 400px;
    filter: saturate(280%);
}
</style>

案例:fallback

typescript 复制代码
<template>
    <div class="app">
        <h2>我是app组件</h2>
        <Suspense>
            <template v-slot:default>
                <Child/>
            </template>
            <template v-slot:fallback>
                <h2>加载中....</h2>
            </template>
        </Suspense>
    </div>

</template>

<script lang="ts" setup name="App">
    import Child from './Child.vue'
    import { Suspense } from 'vue';
</script>

<style scoped>
    .app {
        background-color: #add;
        border-radius: 10px;
        padding: 10px;
        box-shadow: 0 0 10px;
    }
</style>
typescript 复制代码
<template>
    <div class="child">
        <img :src="message">
    </div>

</template>

<script lang="ts" setup name="Child">
    import {ref} from 'vue'
    import axios from 'axios';
    let sum = ref(0)
    let {data:{message}} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')
    console.log(message)
</script>

<style scoped>
    .child {
        background-color: #bce;
        border-radius: 10px;
        padding: 10px;
        box-shadow: 0 0 10px;
    }
</style>

app相关的操作

main.ts

typescript 复制代码
import {createApp} from 'vue'
import App from './App.vue'
import Hello from './Hello.vue'

const app = createApp(App)

app.component('Hello',Hello)
app.config.globalProperties.x = 99
declare module 'vue' {
    interface ComponentCustomProperties {
        x:number
    }
}
app.directive('beauty',(element,{value})=>{
    element.innerText += value
    element.style.color = 'green'
    element.style.backgroundColor = 'yellow'
})
app.mount('#app')
// setTimeout(()=>{
//     app.unmount()
// },2000)

App.vue

typescript 复制代码
<template>
    <div class="app">
        <h2>我是app组件</h2>
        <Hello/>
        <Child/>

    </div>

</template>

<script lang="ts" setup name="App">
    import Child from './Child.vue'
    
</script>

<style scoped>
    .app {
        background-color: #add;
        border-radius: 10px;
        padding: 10px;
        box-shadow: 0 0 10px;
    }
</style>

Child.vue

typescript 复制代码
<template>
    <div class="child">
        <h2>我是child组件</h2>
        <h3 >当前求和为:{{ sum }}</h3>
        <h3 v-beauty="sum">差值</h3>
        <Hello/>
    </div>

</template>

<script lang="ts" setup name="Child">
    import {ref} from 'vue'
    let sum  = ref(3)
</script>

<style scoped>
    .child {
        background-color: #bce;
        border-radius: 10px;
        padding: 10px;
        box-shadow: 0 0 10px;
    }
</style>

案例:作用域插槽

Father.vue

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <div class="content">
            <Game>
                <template v-slot:games="params">
                    <ul>
                        <li v-for="g in params.games" :key="g.id">{{ g.name }}</li>

                    </ul>

                </template>
            </Game>
            <Game v-slot:games="{games}">
                <ol>
                    <li v-for="g in games" :key="g.id">{{ g.name }}</li>

                </ol>
            </Game>
            <Game v-slot:games="params">
                    <h3 v-for="g in params.games" :key="g.id">{{ g.name }}</h3>

            </Game>
        </div>

    </div>
</template>

<script setup lang="ts" name="Category">
import Game from './Game.vue';



</script>

<style scoped>
.father {
    background-color: rgb(165, 164, 164);
    padding: 10px;
    border-radius: 10px;
}

.content {
    display: flex;
    justify-content: space-evenly;
}

img,
video {
    width: 100%;
}
</style>

Child.vue

typescript 复制代码
<template>
    <div class="game">
        <h2>游戏列表</h2>
        <slot name ="games" :games="games"></slot>
    </div>
</template>

<script setup lang="ts" name="Game">
    import {reactive } from 'vue';
    let games = reactive([
        {id:'001',name:'英雄联盟'},
        {id:'002',name:'王者农药'},
        {id:'003',name:'红色警戒'},
        {id:'004',name:'斗罗大陆'},
    ])
</script>

<style scoped>
.game {
    width: 200px;
    height: 300px;
    background-color: skyblue;
    border-radius: 10px;
    box-shadow: 0 0 10px;
}
h2 {
        background-color: orange;
        text-align: center;
        font-size: 14px;
        font-weight: 800;
    }
</style>

案例:组件通信1

Father.vue

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <h4>父亲的玩具:{{ car }}</h4>
        <h4>儿子的玩具:{{ toy }}</h4>
        <Child :car="car" :sendToy="getToy"/>
    </div>
</template>

<script setup lang="ts" name="Father">
    import Child from './Child.vue'
    import {ref} from 'vue'
    let car = ref('帕拉梅拉')
    let toy = ref('')
    function getToy(v:string){
        toy.value = v
    }
</script>
<style scoped>
    .father {
        background-color: rgb(165,164,164);
        padding: 20px;
        border-radius: 10px;
    }
</style>

Child.vue

typescript 复制代码
<template>
    <div class="child">
        <h3>子组件</h3>
        <h4>儿子的玩具:{{   toy }}</h4>
        <h4>父亲的玩具:{{ car }}</h4>
        <button @click="sendToy(toy)">玩具给父亲</button>
    </div>
</template>

<script setup lang="ts" name="Child">
   import {ref} from 'vue'
    let toy = ref('奥特玛')
    defineProps(['car','sendToy'])
    function send() {

    }
</script>

<style scoped>
    .child {
        background-color: skyblue;
        padding:10px;
        box-shadow: 0 0 10px black;
        border-radius: 10px;
    }
</style>

案例:组件通信2-customEvent

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <h4 v-show="toy">子给的玩具:{{ toy }}</h4>
      <!-- //  <button @click="test()">点我</button> -->
        <Child @send-toy="saveToy"/>
    </div>  
</template>

<script setup lang="ts" name="Father">
    import Child from './Child.vue'
    import {ref} from 'vue'
    let toy = ref('')
    function saveToy(val:string) {
        console.log('saveToy',val)

        toy.value = val
    }
</script>

<style scoped >
    .father {
        background-color: rgb(165,164,164);
        padding: 20px;
        border-radius: 10px;
    }
    .father button {
        margin-right: 5px;
    }
</style>
typescript 复制代码
<template>
    <div class="child">
        <h3>子组件</h3>
        <h4>玩具:{{ toy }}</h4>
        <button @click="emit('send-toy',toy)">测试</button>
    </div>
</template>

<script setup lang="ts" name="Child">
import { ref } from 'vue';

let toy = ref('奥特玛')
const emit = defineEmits(['send-toy'])
</script>

<style scoped>
    .child {
        background-color: rgb(76,209,76);
        padding: 10px;
        margin-top: 10px;
        box-shadow: 0 0 10px black;
        border-radius: 10px;
    }
</style>

案例:组件通信3-mitt

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <Child1 />
        <Child2 />
</div>
</template>

<script setup lang="ts" name="Father">
    import Child2 from './Child2.vue';
    import Child1 from './Child1.vue';
</script>

<style scoped>
    .father{
        background-color: yellow;
        padding: 20px;
        border-radius: 10px;
    }
</style>
typescript 复制代码
<template>
    <div class="child1">
        <h3>子组件1</h3>
        <h4>玩具:{{ toy }}</h4>
        <button @click="emitter.emit('send-toy',toy)">玩具给弟弟</button>
    </div>
</template>


<script setup lang="ts" name="Child1">
    import {ref} from 'vue'
    import emitter from '@/utils/emitter';
    let toy = ref('奥特曼')
</script>

<style scoped>
    .child1 {
        margin-top: 50px;
        background-color: skyblue;
        padding: 10px;
        box-shadow: 0 0 10px black;
        border-radius: 10px;
    }
    .child1 button {
        margin-right: 10px;

    }
</style>
typescript 复制代码
<template>
    <div class="child2">
        <h3>子组件2</h3>
        <h4>电脑::{{ computer }}</h4>
        <h4>玩具:{{ toy }}</h4>
    </div>
</template>


<script setup lang="ts" name="Child2">
import { onUnmounted, ref } from 'vue';

let computer = ref('联想')
let toy = ref('')
//数据
import emitter from '@/utils/emitter';
emitter.on('send-toy', (val: any) => {
   console.log('Received value:', val);  // 确认 val 的值
   toy.value = val;  // 更新 toy 的值
});
onUnmounted(()=>{
    emitter.off('send-toy')
})
</script>
<style scoped>
.child2 {
    margin-top: 50px;
    background-color: rgb(133, 112, 218);
    padding: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
}

.child1 button {
    margin-right: 10px;

}
</style>

案例:组件通信4

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <!---v-model 用在html标签上-->
        <!-- <input type="text" v-model="username"> -->
        <!--<input type="text" :value="username" @input="username"=(<HTMLInputElement>$event.target).value-->
        <!-- <AtHome 
        :modelValue="username" @update:modelValue="username = $event"/>
    -->
    <AtHome v-model:name="username" v-model:pwd="password"/>
    <!-- <AtHome v-model="username" /> -->
    </div>
</template>

<script setup lang="ts" name="Father">
import { ref } from "vue"
import AtHome from "./AtHome.vue";
let username = ref('zhangsan')
let password = ref('123456')
</script>

<style scoped>
.father {
    padding: 20px;
    background-color: rgb(165, 164, 164);
    border-radius: 10px;
}
</style>
typescript 复制代码
<template>
    <input type="text"
    :value="name"
    @input="emit('update:name',(<HTMLInputElement>$event.target).value)">


    <input type="text"
    :value="pwd"
    @input="emit('update:pwd',(<HTMLInputElement>$event.target).value)">
</template>

<script setup lang="ts" name="AtHome">
    defineProps(['name','pwd'])
    const emit = defineEmits(['update:name','update:pwd'])
</script>

<style scoped>
input {
    border:2px solid black;
    background-image: linear-gradient(45deg,red,yellow,green);
    height:30px;
    font-size:20px;
    color: white;
}
</style>

案例:组件通信5

typescript 复制代码
<template>
    <div class="grand-child">
        <h3>孙组件</h3>
        <h4>{{ a }}</h4>
        <h4>{{ b }}</h4>
        <h4>{{ c }}</h4>
        <h4>{{ d }}</h4>
        <button @click="updateA(1)">点我更新爷爷</button>
    </div>
</template>


<script setup lang="ts" name="GrandChild">
defineProps(['a','b','c','d','updateA'])
</script>

<style scoped>
    .grand-child {
        background-color: orange;
        padding:20px;
        margin-top: 20px;

        border-radius: 10px;
        box-shadow: 0 0 10px black;
    }
</style>
typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <h4>a:{{ a }}</h4>
        <h4>b:{{ b }}</h4>
        <h4>c:{{ c }}</h4>
        <h4>d:{{ d }}</h4>

        <Child :a="a" :b="b" :c="c" :d="d" :updateA="updateA"/>
    </div>
</template>


<script setup lang="ts" name="Father">
    import Child from "./Child.vue"
    import {ref} from 'vue'
    let a = ref(1)
    let b = ref(2)
    let c = ref(3)
    let d = ref(4)
    function updateA(val:number) {
        a.value += val
    }
</script>

<style scoped>
    .father {
        background-color: rgb(165,164,164);
        padding:20px;
        border-radius: 10px;
    }
</style>
typescript 复制代码
<template>
    <div class="child">
        <h3>子组件</h3>
        <GrandChild v-bind="$attrs"/>
    </div>
</template>


<script setup lang="ts" name="Child">
    import GrandChild from "./GrandChild.vue"
</script>

<style scoped>
    .child {
        background-color: skyblue;
        padding:20px;
        margin-top: 20px;

        border-radius: 10px;
        box-shadow: 0 0 10px black;
    }
</style>

案例:组件通信6

typescript 复制代码
<template>
<div class="father">
    <h3>父组件</h3>
    <h4>房产:{{ house }}</h4>
    <button @click="changeToy">修改child1玩具</button>
    <Child1 ref="c1"/>
    <button @click="changeToy2">修改child2玩具</button>
    <button @click="getAllChild($refs)">获取所有子组件实例对象</button>
    <Child2 ref="c2"/>
</div>
</template>
<script setup lang="ts" name="Father">
    import Child1 from './Child1.vue'
    import Child2 from './Child2.vue'
    import { ref } from 'vue'
    let house = ref(4)
    let c1 = ref()
    function changeToy(){
        console.log(c1.value)
        c1.value.toy = "杰瑞"
    }
    let c2 = ref()
    function changeToy2(){
        c2.value.computer = "华硕"

    }
    function getAllChild(obj:any){
        for (let key in obj){
            obj[key].book +=3
        }
    }
    defineExpose({house})
</script>

<style scoped >
    .father {
        background-color: rgb(165,164,164);
        padding:20px;
        border-radius: 10px;
    }
</style>
typescript 复制代码
<template>
    <div class="child1">
        <h3>子组件1</h3>
        <h4>儿子1的玩具:{{ toy }}</h4>
        <h4>儿子1的书籍:{{ book }}本</h4>
        <button @click="minusHouse($parent)">干掉父亲的一套房产</button>
    </div>
</template>
<script setup lang="ts" name="Child2">
import { ref } from 'vue';

let toy = ref('汤姆')
let book = ref(3)
defineExpose({toy,book})
function minusHouse(parent:any) {
    parent.house -= 1
}
</script>

<style scoped>
.child1 {
    margin-top: 20px;
    padding: 20px;
    background-color: skyblue;
    border-radius: 10px;
    box-shadow: 0 0 10px black;
}
</style>
typescript 复制代码
<template>
    <div class="child2">
        <h3>子组件2</h3>

        <h4>儿子2的玩具:{{ computer }}</h4>
        <h4>儿子2的书籍:{{ book }}本</h4>
    </div>
    </template>
    <script setup lang="ts" name="Child2">
    import { ref } from 'vue';

let computer = ref('联想')
let book = ref(6)
defineExpose({computer,book})

    </script>
    
    <style scoped >
        .child2 {
            margin-top: 20px;
            padding:20px;
            background-color: orange;
            border-radius: 10px;
            box-shadow: 0 0 10px black;
        }
    </style>

案例:组件通信7

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <h4>银子:{{ money }}</h4>
        <h4>车子: 一辆{{ car.brand }}车,价值{{ car.price }}万元</h4>
        <Child/>
    </div>

</template>

<script setup lang="ts" name="Father">
    import Child from './Child.vue'
    import {ref,reactive, provide} from 'vue'
    let money = ref(100)
    let car = reactive({
        brand:'奔驰',
        price:100,
    })
    function updateMoney(val:number){
        money.value -= val
    }
    provide('moneyContext',{money,updateMoney})
    provide('che',car)
</script>

<style scoped>
    .father {
        background-color: rgb(165,164,164);
        padding:20px;
        border-radius: 10px;
    }
</style>
typescript 复制代码
<template>
    <div class="child">
        <h3>子组件</h3>
        <GrandChild/>
    </div>

</template>

<script setup lang="ts" name="Child">
    import GrandChild from './GrandChild.vue'
</script>

<style scoped>
    .father {
        margin-top: 20px;
        background-color: skyblue;
        padding:20px;
        border-radius: 10px;
        box-shadow: 0 0 10px black;
    }
</style>
typescript 复制代码
<template>
    <div class="grand-child">
        <h3>我是孙组件</h3>
        <h4>钱:{{ money }}</h4>
        <button @click="updateMoney(6)">花爷爷的钱</button>
    </div>
</template>

<script setup lang="ts" name="GrandChild">
import { inject } from 'vue';

let {money,updateMoney} = inject('moneyContext',{money:0,updateMoney:(parma:number)=>{}})
let car = inject('car',{brand:'未知',price:0})
</script>

<style scoped>
.grand-child{
    background-color: orange;
    padding:20px;
    border-radius: 10px;
    box-shadow: 0 0 10px black;
}
</style>

案例:组件通信8

typescript 复制代码
<template>
    <div class="father">
        <h3>父组件</h3>
        <div class="content">
            <Category >
                <template v-slot:s2>
                    <ul>
                        <li v-for="g in games" :key="g.id">{{g.name}}</li>
                    </ul>
                </template>
                <template v-slot:s1>
                    <h2>热门游戏列表</h2>
                </template>
            </Category>
            <Category >
                <template v-slot:s2>
                    <img src="./tmp.png" alt="111">
                </template>
                <template v-slot:s1>
                    <h2>今日美食城市</h2>
                </template>
            </Category>
            <Category >
                <template #s1>
                    <h2>今日影视推荐</h2>
                </template>
                <template #s2>
                    <video src="./1.mp4" alt="222" controls></video>
                </template>
            </Category>

        </div>
    </div>
</template>

<script setup lang="ts" name="Category">
import { reactive,ref } from 'vue';
import Category from './Category.vue';
let games = reactive([
    {id:'001',name:'英雄联盟'},
    {id:'002',name:'王者农药'},
    {id:'003',name:'红色警戒'},
    {id:'004',name:'斗罗大陆'},
])
let imgUrl = ref('@/09_slot/tmp.png')
let mp4Url = ref('./1.mp4')

</script>

<style scoped>
    /* .category {
        background-color: rgb(165,164,164);
        padding:10px;
        border-radius: 10px;
    } */
    .content {
        display: flex;
        justify-content: space-evenly;
    }
    img,video {
        width: 100% ;
    }
    h2 {
        background-color: orange;
        text-align: center;
        font-size: 14px;
        font-weight: 800;
    }
</style>
typescript 复制代码
<template>
    <div class="category">
        <h2>{{ title }}</h2>
        <slot name="s1">默认内</slot>
        <slot name="s2">默认内</slot>
    </div>
</template>

<script setup lang="ts" name="Category">
defineProps(['title'])
</script>

<style scoped>
    .category {
        background-color: skyblue;
        border-radius: 10px;
        box-shadow: 0 0 10px;
        padding:10px;
        width:200px;
        height:300px;
    }
    h2 {
        background-color: orange;
        text-align: center;
        font-size: 14px;
        font-weight: 800;
    }
</style>
相关推荐
饮长安千年月1 小时前
Linksys WRT54G路由器溢出漏洞分析–运行环境修复
网络·物联网·学习·安全·机器学习
红花与香菇2____1 小时前
【学习笔记】Cadence电子设计全流程(二)原理图库的创建与设计(上)
笔记·嵌入式硬件·学习·pcb设计·cadence·pcb工艺
发呆的薇薇°3 小时前
vue3 配置@根路径
前端·vue.js
luoluoal3 小时前
基于Spring Boot+Vue的宠物服务管理系统(源码+文档)
vue.js·spring boot·宠物
luckyext3 小时前
HBuilderX中,VUE生成随机数字,vue调用随机数函数
前端·javascript·vue.js·微信小程序·小程序
一天八小时4 小时前
Docker学习进阶
学习·docker·容器
前端没钱4 小时前
前端需要学习 Docker 吗?
前端·学习·docker
拥有一颗学徒的心4 小时前
鸿蒙第三方库MMKV源码学习笔记
笔记·学习·性能优化·harmonyos
车端域控测试工程师4 小时前
【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑰】
经验分享·学习·汽车·测试用例·capl
车端域控测试工程师4 小时前
【ISO 14229-1:2023 UDS诊断(ECU复位0x11服务)测试用例CAPL代码全解析⑪】
经验分享·学习·汽车·测试用例·capl