Vue3-Composition-API-学习笔记

简介: Vue3-Composition-API-学习笔记

01.Setup函数的体验

App.vue

<template>
  <div>
    <h2>当前计数:{{ counter }}</h2>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
  </div>
</template>
<script>
 import useCounter from './hooks/useCounter'
  export default {
    setup(){
      // const { counter,increment,decrement } = useCounter()
      // return { counter,increment,decrement } 
      return {
        ...useCounter()
      }
    }
  }
</script>
<style scoped>
</style>

useCounter.js

import { ref } from 'vue'
export default function useCounter(){
  const counter = ref(100)
  const increment = () => {
    counter.value++
    console.log(counter.value)
  }
  const decrement = () =>{
    counter.value--
  }
  return { 
    counter,
    increment,
    decrement 
  }
}

02.Setup定义数据

App.vue

<template>
  <div>
    <form action="">
      账号:<input  type="text" v-model="account.username">
      密码:<input  type="password" v-model="account.password">
    </form>
  </div>
</template>
<script>
   import { reactive,ref } from 'vue';
  export default{
    setup(){
      // 定义相应式数据:reactive
      const info = ref({})
      console.log(info.value)
      // 1. reactive的应用场景
      // 1.1 条件1:reactive的应用场景
      // 1.2 条件2:多个数据之间是有关系/联系的(聚合的数据,组织在一起会有特定的数作用)
      const account = reactive({
        username:"coderwhy",
        password:"123456"
      })
      return {
        account
      }
    }
  }
</script>
<style scoped>
</style>

App1.vue

<template>
  <div>
    <h2>message:{{ message }}</h2>
    <button @click="changeMessage">修改message</button>
    <hr>
    <h2>账号:{{ account.username }}</h2>
    <h2>密码:{{ account.password }}</h2>
    <button @click="changeAccount">修改账号</button>
    <hr>
    <!-- 默认清空下在template中使用ref时,vue会自动进行千层解包(取出value) -->
    <h2>当前计数:{{ counter }}</h2>
    <button @click="increment">+1</button>
    <hr>
    <!-- 使用的时候 -->
    <h2>当前计数:{{ info.counter }}</h2>
    <!-- 修改的时候需要写.value -->
    <button @click="info.counter.value++">+1</button>
  </div>
</template>
<script>
  import { reactive,ref } from 'vue';
  export default {
    setup(){
      // 1.定义普通的数据
      // 缺点:数据不是响应式的
      let message = "Hello World"
      // 2.定义响应式数据
      // 2.1 reactive函数:定义复杂类型数据
      const account = reactive({
        username:"coderwhy",
        password:"123456"
      })
     
      function changeAccount(){
        account.username = "kobe"
      }
      
      function  changeMessage() {
        message = "你好啊,李焕英"
        console.log(message)
      }
      // 2.2 counter定义响应式数据
      // ref函数:定义简单类型的数据
      const counter = ref(0)
      // const counter = reactive({
      //   counter:0
      // })
      function increment(){
        counter.value++
      }
      // 3.ref是浅层解包
      const info = {
        counter
      }
      return {
        message,
        changeAccount,
        changeMessage,
        counter,
        account,
        increment,
        info
      }
    }
  }
</script>
<style scoped>
</style>

03.setup其他函数

App.vue

<template>
  <div>
    <h2>App</h2>
    <ShowInfo @change_name="change_name" :reinfo="reinfo" @change_rename="change_rename" :info="info"></ShowInfo>
  </div>
</template>
<script>
  import { reactive,readonly } from 'vue';
  import ShowInfo from './ShowInfo.vue';
  export default {
    components:{
      ShowInfo
    },
    setup(){
      const info = reactive({
        name:'kebo',
        age:18,
        sex:'男'
      })
      const reinfo = readonly(info)
      function change_name(eve){
        info.name = eve
      }
      function change_rename(reeve){
        info.name = reeve
      }
      return {
        info,
        change_name,
        reinfo,
        change_rename
      }
    },
   
  }
</script>
<style scoped>
</style>

ShowInfo.vue

<template>
  <div>
    <h2>info: {{ info }}</h2>
    <button @click="change_name">改变info.name</button>
    <hr>
    <h2>reinfo:{{ reinfo }}</h2>
    <!-- <button @click="reinfo.name='hahaha'">修改reinfo.name</button> -->
    <button @click="change_rename">修改reinfo.name</button>
  </div>
</template>
<script>
  
  export default {
    props:{
      info:{
        type:Object,
        default:() => ({})
      },
      reinfo:{
        type:Object,
        default:() => ({})
      },
    },
    emits:['change_name','change_rename'],
    setup(props,context){
      function change_name(){
        context.emit("change_name",'why')
      }
      function change_rename(){
        context.emit("change_rename",'tom')
      }
      return {
        change_name,
        change_rename
      }
    },
    methods:{
    }
  }
</script>
<style scoped>
</style>

04.Setup中toRefs

App.vue

<template>
  <div>
    <div>info:{{ info.name }} -- {{ info.age }}</div>
    <div>name:{{ name }}---age:{{ age }}</div>
    <button @click="age++">age+1</button>
    <hr>
    <div>height:{{ height }}</div>
    <button @click="height++">height++</button>
  </div>
</template>
<script>
  import { reactive,toRefs,toRef } from "vue";
  export default {
    setup(){
      const info = reactive({
        name:'tom',
        age:18,
        height:188
      })
      // reactive被结构将会编程普通的数据,失去响应式
      const { name,age } = toRefs(info)
      const height = toRef(info,"height")
      return {
        info,
        name,
        age,
        height
      }
    }
  }
</script>
<style scoped>
</style>

05.Setup中computed

App.vue

<template>
  <div>
    <div>fullname:{{ fullname }}</div>
    <button @click="setFullname">设置fullname</button>
    <div>scoreLevel:{{ scoreLevel }}</div>
  </div>
</template>
<script>
  import { ref,reactive,computed } from 'vue'
  export default {
    setup(){
      // 1.定义数据
      const names = reactive({
        firstName:"kobe",
        lastName:"bryant"
      })
      // const fullname = computed(()=>{
      //   return names.firstName +" "+ names.lastName
      // })
      const fullname = computed({
        set:function(newValue){
          const tempNames = newValue.split(" ")
          names.firstName = tempNames[0]
          names.lastName = tempNames[1]
        },
        get:function(){
          return names.firstName + " " + names.lastName
        }
      })
      console.log(fullname)
      function setFullname(){
        fullname.value = "coder why"
        console.log(names)
      }
      // 2.定义score
      const score = ref(89)
      const scoreLevel = computed(()=>{
        return score.value >= 60 ? "及格" : "不及格"
      })
      
      return {
        names,
        fullname,
        scoreLevel,
        setFullname
      }
    }
  }
</script>
<style scoped>
</style>

06.Setup中ref引入元素

App.vue

<template>
  <div>
    <!-- 1.获取元素 -->
    <h2 ref="titleRef"> 我是标题 </h2>
    <button ref="btnRef">按钮</button>
    <ShowInfo ref="ShowInfoRef"></ShowInfo>
    <button @click="getElements">获取元素</button>
  </div>
</template>
<script>
  import { ref,onMounted } from 'vue'
  import ShowInfo from './ShowInfo.vue'
  export default {
    // mounted(){
    //   console.log(this.$refs.title)
    //   console.log(this.$refs.btn)
    // }
    components:{
      ShowInfo
    },
    setup(){
      const titleRef = ref()
      const btnRef = ref()
      const ShowInfoRef = ref()
      // mounted的生命周期函数
      onMounted(()=>{
        console.log(titleRef.value)
        console.log(btnRef.value)
        console.log(ShowInfoRef.value)
        ShowInfoRef.value.ShowInfoFoo()
      })
      function getElements(){
        console.log(titleRef.value)
      }
      return {
        titleRef,
        getElements,
        btnRef,
        ShowInfoRef
      }
    }
  }
</script>
<style scoped>
</style>

ShowInfo.vue

<template>
  <div>
    <div>ShowInfo</div>
  </div>
</template>
<script>
  export default {
    // methods:{
    //   function ShowInfoFoo(){
    //     console.log("showInfo foo function")
    //   }
    // },
    setup(){
      function ShowInfoFoo(){
        console.log("showInfo foo function")
      }
      return {
        ShowInfoFoo
      }
    }
  }
</script>
<style scoped>
</style>

07.Setup生命周期函数

App.vue

<template>
  <div>
  </div>
</template>
<script>
  import { onMounted } from 'vue'
  export default {
    // created(){
    // },
    // beforeMount(){
    // },
    // mounted(){
    // },
    // beforeUpdate(){
    // },
    // updated(){
    // }
    setup(){
      // 在执行setup函数的过程中,你需要注册别的生命周期函数
      onMounted(()=>{
        console.log("onmounted")
      })
    }
  }
</script>
<style scoped>
</style>

08.Setup-Provide-Inject

App.vue

<template>
  <div>
    <div>App:{{ name }} --</div>
    <ShowInfo></ShowInfo>
  </div>
</template>
<script>
  import ShowInfo from './ShowInfo.vue';
  import { provide,ref } from 'vue'
  export default {
    components:{
      ShowInfo
    },
    setup(){
      const name = ref("why")
      provide("name",name)
      provide("age",18)
      return {
        name,
      }
    }
  }
</script>
<style scoped>
</style>

ShowInfo.vue

<template>
  <div>
    <div>showInfo:{{ name }} -- {{ age }}</div>
    <button @click="name = 'kobe'">app btn</button>
  </div>
</template>
<script>
import { inject } from 'vue';
  export default {
    setup() {
        const name = inject("name");
        const age = inject("age");
        return {
            name,
            age
        };
    },
}
</script>
<style scoped>
</style>

09.Setup-侦听数据变化

App.vue

<template>
  <div>
    <div>当前计数 {{  counter }}</div>
    <button @click="counter++">+1</button>
    <button @click="change_name">修改name</button>
  </div>
</template>
<script>
  import { ref,watchEffect } from 'vue'
  export default {
    setup(){
      const counter = ref(0);
      const name = ref('why');
      // 1.watchEffect传入的函数默认会直接被执行
      // 2.在执行过程中,会自动的收集依赖(以来那些响应式的数据)
      const stopWatch = watchEffect(()=>{
        console.log("------",counter.value,name.value)
        // 判断counter.value > 10
        if(counter.value >= 10){
          stopWatch()
        }
      })
      function change_name(){
        name.value='kobi'
      }
      return {
        counter,
        change_name,
        name
      }
    }
  }
</script>
<style scoped>
</style>

App-watch.vue

<template>
  <div>
    <h2>message:{{ message }}</h2>
    <button @click="change_message">修改message</button>
    <button @click="change_info">修改info</button>
  </div>
</template>
<script>
  // import { watch } from 'fs'
import { ref,watch,reactive } from 'vue'
  export default {
    setup(){
      const message = ref('hello');
      const info = reactive({
        name:'tom',
        age:18,
        friend:{
          name:"kobe"
        }
      })
      function change_message(){
        message.value = '你好!'
      }
      function change_info(){
        info.name = 'hhhhh'
      }
      // 2.侦听变化
      watch(message,(newValue,oldValue)=>{
        console.log(newValue,oldValue)
      })
      // watch(info,(newValue,oldValue)=>{
      //   console.log(newValue,oldValue)
      //   console.log(newValue == oldValue)
      // },{
      //   immediate:true // 深度侦听
      // })  
      // 3.监听reactive数据变化后,获取普通对象
      watch(()=>({ ...info }),(newValue,oldValue)=>{
        console.log(newValue,oldValue)
      },{
        immediate:true,
        deep:true
      })
      return {
        change_message,
        message,
        info,
        change_info
      }
    }
  }
</script>
<style scoped>
</style>

10.Setup-Hooks练习

App.vue

<template>
  <div>
    <div>App:{{ counter }}</div>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
    <button @click="index_tab('首页-热门')">首页-热门</button>
    <button @click="index_tab('首页-流行')">首页-流行</button>
    <button @click="index_tab('首页-歌单')">首页-歌单</button>
    <hr>
    <HomeCom></HomeCom>
    <hr>
    <AboutCom></AboutCom>
  </div>
</template>
<script>
import HomeCom from './views/HomeCom.vue';
import AboutCom from './views/AboutCom.vue';
import useCounter from './hooks/useCounter';
import useTitle from './hooks/useTitle';
export default {
  components: {
    HomeCom,
    AboutCom
  },
  setup() {
    const title = useTitle("首页")
    function index_tab(eve){
      title.value = eve
    }
    return {
      index_tab,
      ...useCounter()
    }
  }
}
</script>
<style scoped></style>

AboutCom.vue

<template>
  <div>
    
    <div>About:{{ counter }}</div>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
    <button @click="change_title">修改title</button>
  </div>
</template>
<script>
  import useCounter from '../hooks/useCounter';
  import useTitle from '../hooks/useTitle';
  export default {
    setup(){
      const title = useTitle("首页")
      // 监听事件点击
      function change_title(){
        title.value = '关于';
      }
      return {
        change_title,
        ...useCounter()
      }
    }
  }
</script>
<style scoped>
</style>

HomeCom.vue

<template>
  <div>
    <div>Home:{{ counter }}</div>
    <button @click="increment">+1</button>
    <button @click="decrement">-1</button>
  </div>
</template>
<script>
  import useCounter from '../hooks/useCounter';
  export default {
    setup(){
      return {
        ...useCounter()
      }
    }
  }
</script>
<style scoped>
</style>

useCounter.js

import { ref,onMounted } from 'vue'
export default function useCounter(){
  const counter = ref(0)
  function increment(){
    counter.value++
  }
  function decrement(){
    counter.value--
  }
  onMounted(()=>{
    setTimeout(()=>{
      counter.value = 989
    },1000)
  })
  return {
    counter,
    increment,
    decrement
  }
}

useTitle.js

import { watch,ref } from "vue"
export default function useTitle(titleValue){
  // document.title = title
  // 定义ref的引入数据
  const title = ref(titleValue)
  // 监听title的改变
  watch(title,(newValue)=>{
    document.title = newValue
  },{
    immediate:true // 第一次不执行
  })
  // 返回ref值
  return title
}

11.script_setup语法

App.vue

<template>
  <div>
    <div>App</div>
    <button @click="changeMessage">修改message</button>
    <show-info ref="showInfoRef" @info-btn-click="infoBtnClick" name="why" :age="18"></show-info> 
    <!-- <ShowInfo></ShowInfo>
    <ShowInfo></ShowInfo>
    <ShowInfo></ShowInfo> -->
  </div>
</template>
<script setup>
// 1. 所以定义在顶层中的代码,都是默认暴露给template可以使用
  import { onMounted,ref } from 'vue';
  import ShowInfo from './ShowInfo.vue';
  // 2. 定义响应式数据
  const message = ref("hello world")
  console.log(message)
  // 3. 定义绑定的函数
  function changeMessage(){
    message.value = "你好,世界"
  }
  function infoBtnClick(eve){
    console.log("监听到infoBtnClick内部的info",eve)
  }
   
  // 4. 获取组件实例
  const showInfoRef  = ref();
  onMounted(()=>{
    showInfoRef.value.foo()
    console.log("showInfoRef.value.message",showInfoRef.value.message)
  })
</script>
<style scoped>
</style>

ShowInfo.vue

<template>
  <div>
    message:-- {{ name }} --- {{ age }}
    <button @click="showInfoBtnClick">showinfo</button>
  </div>
</template>
<script setup>
import { defineProps,defineEmits,defineExpose } from 'vue';
  const message = "hello world"
  // console.log(message)
  //  定义props const props = 
  defineProps({
    name:{
      type:String,
      default:"默认值"
    },
    age:{
      type:Number,
      default:0
    }
  }) 
  // 绑定函数,并发出事件
  const emits = defineEmits(["infoBtnClick"])
  function showInfoBtnClick(){
    emits("infoBtnClick","showInfo内部发生了点击")
  }
  // 定义foo的函数
  function foo(){
    console.log("foo function")
  }
  defineExpose({
    foo,
    message
  })
  
</script>
<style scoped>
</style>

感谢大家观看,我们下次见

目录
相关文章
|
弹性计算 安全 网络协议
VPC的基本原理|学习笔记
快速学习VPC的基本原理
JAVA并发编程系列(7)Semaphore信号量剖析
腾讯T2面试,要求在3分钟内用不超过20行代码模拟地铁安检进站过程。题目设定10个安检口,100人排队,每人安检需5秒。实际中,这种题目主要考察并发编程能力,特别是多个线程如何共享有限资源。今天我们使用信号量(Semaphore)实现,限制同时进站的人数,并通过信号量控制排队和进站流程。并详细剖析信号量核心原理和源码。
|
10月前
|
存储 JavaScript 前端开发
基于 JavaScript/VuePress 搭建的远程工作平台:YuanCheng.works
为了提高团队的协作效率和信息共享能力,许多公司开始探索基于现代技术的远程工作平台。本文将介绍如何利用 JavaScript 和 VuePress 搭建一个高效的远程工作平台,助力团队在灵活的工作环境中实现卓越的协作。
185 56
|
存储 NoSQL 物联网
【MongoDB 专栏】MongoDB 在物联网(IoT)领域的应用
【5月更文挑战第11天】MongoDB,一种灵活可扩展的非关系型数据库,在物联网(IoT)领域中大放异彩。应对海量设备产生的多样化数据,MongoDB的文档型数据结构适应性强,适合存储设备信息及传感器读数。其实时更新、强大查询语言、索引机制和扩展性(通过分片技术)满足物联网的高实时性、复杂查询和数据增长需求。尽管面临数据安全和管理挑战,MongoDB已广泛应用于智能家居、工业 IoT 和智能交通等领域,并有望随着物联网技术进步和与其他领域的融合,如人工智能、大数据,持续发展。未来,优化数据质量、提升并发处理能力将是关键,MongoDB将在物联网的智能未来中扮演重要角色。
925 2
【MongoDB 专栏】MongoDB 在物联网(IoT)领域的应用
|
8月前
|
移动开发 数据可视化 前端开发
tmagic - editor:大厂开源项目,零代码/低代码页面可视化编辑的利器,多端统一方案揭秘!如何用一套代码支持H5/PC,牛牛牛~~~
腾讯推出的开源项目 **tmagic-editor** 是一款所见即所得的页面可视化编辑器,支持H5、PC、TV等多种页面类型。它已应用于腾讯视频会员、腾讯会议等业务,每月生产和发布数百个页面,极大提高了开发效率。通过简单的拖拽和配置,非技术人员也能轻松创建复杂页面。tmagic-editor 支持 Vue2/Vue3 和 React 等多种前端框架,并提供了丰富的扩展功能,满足不同业务需求。
738 3
|
11月前
|
缓存 Java
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
本文介绍了几种常见的锁机制,包括公平锁与非公平锁、可重入锁与不可重入锁、自旋锁以及读写锁和互斥锁。公平锁按申请顺序分配锁,而非公平锁允许插队。可重入锁允许线程多次获取同一锁,避免死锁。自旋锁通过循环尝试获取锁,减少上下文切换开销。读写锁区分读锁和写锁,提高并发性能。文章还提供了相关代码示例,帮助理解这些锁的实现和使用场景。
277 4
java中的公平锁、非公平锁、可重入锁、递归锁、自旋锁、独占锁和共享锁
|
11月前
|
存储 Oracle 关系型数据库
【赵渝强老师】MySQL InnoDB的表空间
InnoDB是MySQL默认的存储引擎,主要由存储结构、内存结构和线程结构组成。其存储结构分为逻辑和物理两部分,逻辑存储结构包括表空间、段、区和页。表空间是InnoDB逻辑结构的最高层,所有数据都存放在其中。默认情况下,InnoDB有一个共享表空间ibdata1,用于存放撤销信息、系统事务信息等。启用参数`innodb_file_per_table`后,每张表的数据可以单独存放在一个表空间内,但撤销信息等仍存放在共享表空间中。
159 6
|
Linux 网络安全 Windows
[linux]frp内网穿透
[linux]frp内网穿透
236 2
|
负载均衡 安全 网络架构
|
Android开发
Android编译出现Warning: Mapping new ns to old ns的解决方案
Android编译出现Warning: Mapping new ns to old ns的解决方案
952 3