一、vue3.0介绍
Vue3.0支持大多数的Vue2的特性,Vue3中设计了一套强大的composition组合API代替Vue2中的optionAPI,复用性更强大了,对TypeScript有更好的支持。
二、创建项目
2.1Vue-cli脚手架搭建项目

2.2、vite搭建项目
Vite是一个web开发构建工具,由于其原生ES模块导入方式,可以实现闪电般的模块热更新;
npm init @vitejs/app<项目名>三、Composition API
3.1是什么?
Composition API也叫组合式API,是Vue3.0的新特性。
通过创建Vue组件,我们可以将接口的可重复部分及其功能提取到可重复的代码部分及其功能提取到可重用的代码段中。
3.2为什么使用CompositionAPI?

3.3函数

3.4(一)setup
setup()函数是vue3.0中,专门为组件提供的新属性,它为我们使用vue3的CompositionAPI新特性提供了统一的入口。
props:组件传入的属性
context:上下文对象
3.5(二)ref
ref接收一个内部值并返回一个响应式且可变的ref对象。ref对象具有指向内部值的单个property.value.
<template>
  <!-- <h3>数量:{{num}}</h3> -->
  <h3>count数量:{{count}}</h3>
  <input type="text" v-model="count">
  <button @click="getCount()">获取</button>
</template>
<script>
    import {ref} from 'vue'
    export default {
        //option API方式
        // data(){
        //     return{
        //         num:0
        //     }
        // }
        //composition API方式
        setup(){//data methods computed watch都是写在setup中
            //直接这样定义 不是响应式的数据
            // const count = 0;
            //创建响应式的数据对象 我们的count 给初始值为0
            const count = ref(0)
            let getCount = ()=>{
                //如果要访问ref() 创建出来响应式数据对象的值 必须通过.value属性才可以
                console.log(count.value)
            }
            //模板中要使用这些变量和方法 都需要调用,所以需要return
            return{
                count,getCount
            }
        }
    }
</script>
<style>
</style>3.5(三)reactive
reactive()函数接收一个普通对象,返回一个响应式的数据对象.响应式转换是“深层”的—它影响所有嵌套property.
3.6(四)toRefs
toRefs将响应式对象转换为普通对象,其中结果对象的每个property都是指向原始对象相应property的ref,当从合成函数返回响应式对象时,toRefs非常有用,这样消费组件就可以在不丢失响应式的情况下对返回的对象进行分解/扩散
3.7(五)computed
<template>
  <hr>
  <input type="text" v-model="test">
  <h2>user:{{test}}</h2>
  <!-- <h3>姓名:{{data.user.name}}</h3> -->
  <h3>姓名:{{user.name}}</h3>
  <li v-for="item in list ">
    {{item}}
  </li>
  <hr>
  <p>
    姓:<input type="text" v-model="firstName">
  </p>
  <p>
    名:<input type="text" v-model="lastName">
  </p>
  <h4>全名:{{fullName}}</h4>
  <button @click="getFullName">获取计算属性</button>
</template>
<script>
  import {ref,toRefs,reactive,computed} from 'vue'
  export default{
    setup(){
      //reactive创建响应式数据对象
      const data = reactive({
        test:"测试",
        user:{
          name:"木道人",
          sex:"男"
        },
        list:["特斯拉","追梦","请叫我小平头"]
      })
      //创建一个响应式对象 user
      const user = reactive({
        firstName:"",
        lastName:""
      })
      //它会根据user的值 创建一个响应式的计算属性fullName 自动计算并返回一个新的响应式数据(ref)
      const fullName = computed(()=>{
        return user.firstName + " " + user.lastName
      })
      const getFullName = ()=>{
        console.log(fullName.value)
      }
      return{
        // 解构响应式对象数据
        /* 用 ...扩展运算结构响应式对象数据,是不可行。因为结构后就变成成了一个普通变量,不在具有响应式的能力 */
        // ...data 
        // toRefs 把一个响应式的对象转换成普通对象,对data进行了包装,再使用...拓展符的方式将data解构
        ...toRefs(data),
        ...toRefs(user),fullName,getFullName
      }
    }
  }
</script>
<style>
</style>3.8(六)watchEffect
在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它

3.9(七)watch
watch()函数用来监视某些数据项的变化,从而触发某些特定的操作,使用之前需要按需导入:
export default{
    setup(props,context){//composition API的入口
      const num = ref(0)
      const str = ref("测试")
      const state = reactive({
        id:101,
        uname:'莫愁'
      })
      //只要num有变化 会触发watch的回调 watch会在创建时自动调用
      // watch(()=>{console.log(num.value)})
      /* val:新的值 oval:旧的值 */
      watch(num,(val,oval)=>{
        console.log(val,oval)
        console.log("c num:",num.value)
      },{//第二个参数obj immediate deep
        immediate:false //默认就是只有数据改变时才会监听,第一次不会执行,设置true第一次也会执行
      })
      //侦听state下的id,数据的变化
      watch(state,(val,oval)=>{
        console.log("id:",val.id,oval)
      },{
        immediate:true ,//默认就是只有数据改变时才会监听,第一次不会执行,设置true第一次也会执行
        deep:true,//开启深度侦听 能够侦听到对象的属性值的变化
      })
      //单个侦听state下的uname
      watch(()=>state.uname,(uname,p)=>{
        console.log(uname,p)
      },{
        immediate:true ,//默认就是只有数据改变时才会监听,第一次不会执行,设置true第一次也会执行
      })
      //const s = toRefs(state)  watch(s.id,()=>{})  等于 ()=>state.id
      //多个侦听数据
      const stop = watch([()=>state.id,()=>state.uname],([id,uname],[oid,oname])=>{
        console.log("id:",id,oid)
        console.log("uname",uname,oname)
      })      
      return{
        num,stop,
        ...toRefs(state)
      }
    }
  }3.10(八)API

四、Provide&inject
4.1provide
provide:向子组件以及子孙组件传递数据。接收两个参数,第一个参数是key.即数据的名称;第二个参数为value,即数据的值

4.2inject
inject:接收父组件或祖先组件传递过来的数据。接收一个参数key,即父组件或祖先组件传递的数据名称

五、vue3.x中集成typescript
5.1为什么要使用ts
类型检查、直接编译到原生的js、引入语法糖。TypeScript的设计目的应该是解决JavaScript的“痛点”:【弱类型、没有命名空间。导致很难模块化、不适合开发大型程序】,另外它还提供了一些语法糖来帮助大家更方便地实践面向对象的编程。
5.2vue-cli(脚手架)安装ts


5.3vite安装ts

5.4定义组件
如果要让TypeScript正确推断Vue组件选项中的类型,需要使用defineComponent全局方法定义组件:
5.5案例代码康康
<template>
  <h2>集成ts与compositionAPI一起使用</h2>
  <h4>姓名:{{uname}}</h4>
  <h4>兴趣:{{hobby}}</h4>
  <h4>年龄:{{age}}</h4>
  <h5>getUNname:{{getUNname(111)}}</h5>
  <p>{{count}}</p>
  <button @click="setCount()">setCount</button>
</template>
<script lang="ts">
  //defineComponent 启用类型校验
  import {defineComponent,reactive,toRefs,ref} from 'vue'
  //约束data中的属性与方法
  interface user{
    uname:string, 
    hobby:string,
    age:number,
    getUNname(msg:string):string
  }
  export default defineComponent ({
    setup(){
      //  三种方式:  :  <>  as
      const data:user = reactive({
        uname:"肖雅涵",
        hobby:"舞蹈",
        age:20,
        getUNname(msg){
          return msg
        }
      })
      //不支持:这种方式约束类型
      // const count:number = ref(0)
      const count= ref<number>(0)
      function setCount(){
        count.value = 123
      }
      return{
        ...toRefs(data),count,setCount
      }
    }
  })
</script>
<style>
</style>六、组合式API结合vue-router
引入setup和Vue的组合式API,开辟了新的可能性,但要充分发挥Vue Router的潜力,我们需要使用一些新的函数来代替访问this和组件内导航守卫。
 因为我们在setup里面没有访问this,所以我们不能在直接访问this.$router或this.$route。作为替代,我们使用useRouter和useRoute函数。
//引入路由
import {useRouter,useRoute} from 'vue-router'
export default{
  setup(){
    const router = useRouter()//等同于this.$router
    const route = useRoute()//等同于this.$route
  }
}七、组合式API结合vuex
如果在使用Vue 中的 组合式API进行编写组件,就不能延续之前的写法(如: this. s t o r e ) 。 由 于 我 们 无 权 访 问 s e t u p 的 内 部 t h i s , 因 此 要 在 s e t u p 中 使 用 s t o r e , 可 以 调 用 该 u s e S t o r e 函 数 。 这 等 效 t h i s . store)。由于我们无权访问setup的内部this,因此要在setup中使用store,可以调用该useStore函数。这等效this. store)。由于我们无权访问setup的内部this,因此要在setup中使用store,可以调用该useStore函数。这等效this.store于使用Option API在组件内进行检索。
7.1setup中访问vuex
请注意,在模板中我们仍然可以访问$store,所以不需要在setup中返回store
八、resolve alias 别名定义
将会被传递到 @rollup/plugin-alias 作为它的 entries。也可以是一个对象,或一个 { find,replacement } 的数组.
当使用文件系统路径的别名时,请始终使用绝对路径。相对路径作别名值将按原样使用导致不会解析到文件系统路径中。
export default defineConfig({
  resolve: {
  alias: {
    "@": path.resolve(__dirname, "src"),
    "@comps": path.resolve(__dirname, "src/components"),
    "@views": path.resolve(__dirname, "src/views"),
    },
  },
  plugins: [vue()],
})或者 数组的形式
import {defineConfig} from 'vite'
import path from "path";
import vue from '@vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: [{
      find: '@',
      replacement: path.resolve(__dirname, 'src')
    },
  {
    find: 'components',
    replacement: path.resolve(__dirname, 'src/components')
  }
],
},
  plugins: [vue()],
});案例
1、模拟后台取到数据











