使用vite创建vue3

npm create vite
或者 yarn create vite

composition API

  • ref
  • reactive
  • torefs
  • watch
  • watch Effact
  • computed

setup

它是组件内使用composition API的入口,执行时机是在beforecreate之前执行的

  • setup的参数

    • props:值为对象,包含:组件外部传递过来,且组件内部声明接受了的属性
    • context:上下文对象

      • attrs:值为对象,包含:组件外部传递过来,但没有在props声明接收了的函数
      • slots:收到的插槽内容,相当于this.$slots
      • emit:分发自定义事件的函数,相当于this.$emit

ref函数:定义普通类型数据

vue3中定义响应式数据:const name : ref(‘小明’);在js中操作:name.value=‘张三’

reactive函数:定义对象类型响应式数据

let obj = reactive({
   type:'前端工程师'salary:'30k'
)
function change(){
    obj.type='后端工程师' //vue3可以直接增删改查数据
    this.$set(obj,'type','后端工程师')//vue2中想要修改数据并渲染必须要用$set,而vue3中可以直接改
}

reactive对比ref

  • 从定义数据角度对比

    1).ref用来定义:基本类型数据

    2).reactive用来定义:对象(或数组)类型数据

    3).ref也可以用来定义对象(或数组)类型数据,它内壁会自动通过reactive转为代理对象

  • 从原理角度对比

    1).ref通过object.defineProperty()的get与set来实现响应式(数据劫持)

    2)reactive通过使用proxy来实现数据劫持,并通过Reflect操作源对象内部的数据

  • 从使用角度对比

    • ref定义数据:操作数据需要.value, 读取数据时模板中直接读取不需要.value
    • reactive定义数据:操作数据与读取数据都不需要.value

computed计算属性

setup(){
    let person = reactive({
        firstName:'张',
        lastName:'三',
    })
    //计算属性简写形式(没有考虑计算属性被修改的情况)
    person.name = computed(()=>{
        return person.firstName+'-'+'person.lastName'
    })
    //计算属性完整写法(考虑读和写)
    person.name = computed(()=>{
        get(){
            return person.firstName+'-'+'person.lastName'
        },
        set(value){  //value是新的值
            const nameArr = value.split('-')
            person.firstName = name[0]
            person.lastName = name[1]
        }
    })
    return{
        firstName,
        lastName,
        name
    }
}

父子传参

父传子:
在父组件中
子组件中用 defineProps({data:string})接受
子传父:

//在子组件中通过defineEmits派发一个事件
const emit = defineEmits(['test']) 
const clickTap = ()=>{
    emit('test',数据) //派发名为test
}
//在父组件中
<Son @test="回调函数"></Son>
在回调函数中第一个参数就是传过来的数据

兄弟间传值

//1. 安装mitt npm install mitt
//2.在main.js中注册挂载到全局
import mitt from 'mitt'
app.config.globalProperties.$mitt = new mitt()
// 发送数据组件
<button @click="sendMitt">$mitt发送数据</button>
function sendMitt() {
				proxy.$mitt.emit('mittFn', 数据)
			}
//接受数据
proxy.$mitt.on('mittFn', (res) => {
				console.log(res) //res就是传过来的数据
			})

配置全局组件

//在main.ts中配置
import Card from './components/Card/index.vue'
createApp(App).component('Card',Card).mount('#app')
//component中第一参数是组件名称,第二个参数是组件实例

动态组件

//让多个组件使用同一个挂载点,并动态切换,这就是动态组件
import A from './A.vue'
import B from './B.vue'
 <component :is="A"></component> // 通过js切换组件
 //如果你把组件实例放到Reactive Vue会给你一个警告runtime-core.esm-bundler.js
 //修改如下:
const tab = reactive<Com[]>([{
    name: "A组件",
    comName: markRaw(A)
}, {
    name: "B组件",
    comName: markRaw(B)
}])

异步组件 Suspense

// 在父组件中引入异步组件
import {  defineAsyncComponent } from 'vue'
const Dialog = defineAsyncComponent(() => import('../../components/Dialog/index.vue'))
// <suspense> 组件有两个插槽。它们都只接收一个直接子节点。default 插槽里的节点会尽可能展示出来。如果不能,则展示 fallback 插槽里的节点。
     <Suspense>
            <template #default>
                <Dialog></Dialog>
            </template>
            <template #fallback>
                <div>loading...</div>
            </template>
</Suspense>

Teleport传送组件

Teleport 是一种能够将我们的模板渲染至指定DOM节点,不受父级style、v-show等属性影响,但data、prop数据依旧能够共用的技术;例如

<teleport to="body">
      <div class="teleport">我是teleport</div>
    </teleport>
    //可以通过to将div放到body里面,也可以使用class或者id放到指定的dom节点里面

keep-alive缓存组件

有时候我们不希望组件被重新渲染影响使用体验;或者处于性能考虑,避免多次重复渲染降低性能。而是希望组件可以缓存下来,维持当前的状态。这时候就需要用到keep-alive组件。
keep-alive对应两个独有的生命周期 onActivated 和 deactivated

<!-- 基本 -->
<keep-alive>
  <component :is="view"></component>
</keep-alive>
<!-- 多个条件判断的子组件 -->
<keep-alive>
  <comp-a v-if="a > 1"></comp-a>
  <comp-b v-else></comp-b>
</keep-alive>
<!-- 和 `<transition>` 一起使用 -->
<transition>
  <keep-alive>
    <component :is="view"></component>
  </keep-alive>
</transition>

keep-alive生命周期的变化:
初次进入时:OnMounted 和 onActivated
退出时:deactivated
再次进入时只会触发:onActivated
只执行一次的放在 onMounted中;组件每次进去执行的方法放在 onActivated中

<keep-alive :include="[]" :exclude="" :max=""></keep-alive>
// include数组中可以填入组件名称name,:include里面包含的组件才会被缓存,没有包含的不会被缓存
:exclude则相反; :max 则最大缓存的组件个数

transition 动画组件

自定义 transition 过度效果,你需要对transition组件的name属性自定义。并在css中写入对应的样式
transition标签中n的ame对应的css标签的设置
name-enter-from:定义进入过渡的开始状态。
name-enter-active:定义进入过渡生效时的状态
name-enter-to:定义进入过渡的结束状态
name-leave-from:定义离开过渡的开始状态。
name-leave-active:定义离开过渡生效时的状态
name-leave-to:离开过渡的结束状态

 <transition name='fade'>
         <div v-if='flag' class="box"></div>
       </transition>
    //对应css   
.fade-enter-from{
   background:red;
   width:0px;
   height:0px;
   transform:rotate(360deg)
}
//开始过度了
.fade-enter-active{
  transition: all 2.5s linear;
}
//过度完成
.fade-enter-to{
   background:yellow;
   width:200px;
   height:200px;
}
//离开的过度
.fade-leave-from{
  width:200px;
  height:200px;
  transform:rotate(360deg)
}
//离开中过度
.fade-leave-active{
  transition: all 1s linear;
}
//离开完成
.fade-leave-to{
  width:0px;
   height:0px;
}

也可以通过自定义过渡class类名;通过自定义class结合animate css动画库

 <transition
            leave-active-class="animate__animated animate__bounceInLeft"
            enter-active-class="animate__animated animate__bounceInRight"
        >
            <div v-if="flag" class="box"></div>
        </transition>

结合gsap动画库使用GreenSock

vue3全局定义函数和变量

由于Vue3没有prototype属性,是使用app.config.globalProperties代替,然后去定义变量和函数
vue2中: vue.prototype.$http = ()=>{}

vue3中: const app = createApp(APP)
app.config.globalProperties.$http = () => {}

CSS样式穿透

vue中使用了scoped后,会在dom结构上会以date-v-hash的方式加在标签上,以保证唯一,不会样式冲突,从而达到样式私有模块化。
在使用UI组件库的时候,很多时候需要改它默认的样式,就需要用到样式穿透:
在样式中使用 :deep(input) 这样就可以了

Pinia 全局状态管理工具 代替Vuex

Pinia.js 有如下特点:

完整的 ts 的支持;
足够轻量,压缩后的体积只有1kb左右;
去除 mutations,只有 state,getters,actions;
actions 支持同步和异步;
代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
无需手动添加 store,store 一旦创建便会自动添加;
支持Vue3 和 Vue2

使用:
1.安装 npm install pinia
2.main.js 引入注册
import {createPinia} from ‘pinia’
const store = createPinia()
app.use(store)
3.初始化仓库


import { defineStore } from 'pinia'
export const useTestStore = defineStore(Names, {
     state:()=>{
         return {
             current:1
         }
     },
     //类似于computed 可以帮我们去修饰我们的值
     getters:{
     },
     //可以操作异步 和 同步提交state
     actions:{
     }
})

4.组件中使用 State是允许直接修改值的


<template>
     <div>
         <button @click="Add">+</button>
          <div>
             {{Test.current}}
          </div>
     </div>
</template>
<script setup lang='ts'>
import {useTestStore} from './store'
const Test = useTestStore()
const Add = () => {
    Test.current++
}
</script>
//批量修改
const Add = () => {
    Test.$patch({
       current:200,
       age:300
    })
//批量修改函数形式
const Add = () => {
    Test.$patch((state)=>{
       state.current++;
       state.age = 40
    })
}
//通过原始对象修改整个实例:$state您可以通过将store的属性设置为新对象来替换store的整个状态,缺点就是必须修改整个对象的所有属性
const Add = () => {
    Test.$state = {
       current:10,
       age:30
    }    
}
// 通过actions修改,在cations中定义方法,然后直接调用actions中的方法
const Add = () => {
     Test.setCurrent()
}

依赖注入(provide/inject)

在父组件中provide注入数据,在所有子孙组件中都能接收到

// 例如在APP.vue组件中
import {provide} from 'vue'
provide('flag',shuju)   // 这样数据就注入完成了,在所有子孙组件中都能接受到
//在子组件中接受数据
import {inject} from 'vue'
let data = inject('flag')  // 这样就拿到了父组件的数据
//当在子组件中修改数据的话,会影响所有子组件中的这个数据

TSX 类似于react写法

1.安装 npm install @vitejs/plugin-vue-jsx -D
2。配置vite.config.ts 、 tsconfig.json

自定义Hooks

优秀的开源库:hooks开源库

useAttrs、useSlots

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。