使用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开源库