vue3归纳总结
vue3 安装方式
vue3 webpack 安装方式
# 全局安装 vue-cli //升级vue-cli到最新
yarn global add @vue/cli
# 或
cnpm install -g @vue/cli
# 命令行创建 project-name 的vue项目 现在会默认创建vue3
vue caeate project-name
vue3 vite 安装方式
#全局安装vite 安装(需要node版本>=12.0.0)
yarn create @vite
#创建vue3项目
npm init vite-app HelloVue
vue3语法格式
options api 和 vue2 写法一样
compostion api:
语法一:
<template>
<div>
{{msg}}
</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
setup () {
const msg = 'hello world' //此处可以写你要声明的变量,方法等
//这个地方是没有this指向,因此使用es6的语法更容易抛出 此处没有抛出所以不会执行
const changeFunc = ()=>{
console.log(msg)
}
return {
msg, //此处必须抛出才能在上面使用
}
}
})
</script>
语法二:
(也叫做setup语法糖) 这个方式的书写不需要 return 你书写的任何变量名会自动帮你调用
<template>
<div>
{{name}}
</div>
</template>
<script setup>
const name = '张三'
</script>
语法三:
vue3能够写jsx语法,并且不用安装依赖 写法类似于react(此处是快乐的源泉,真的很香,大佬们都用这个写开源组件)也有两种写法 这种接近react 18 的function写法 个人推荐 避免this指向混乱
import * as vue from 'vue';
export const Reactions = vue.defineComponent({
setup() {
const name = '张三';
return () => {
return (
<div>
{{name}}
</div>
)
}
}
})
vue3生命周期的改变
setup 创建实例前
onBeforeMount 挂载DOM前
onMounted 挂载DOM后
onBeforeUpdate 更新组件前
onUpdated 更新组件后
onBeforeUnmount 卸载销毁前
onUnmounted 卸载销毁后
去掉了两个函数: beforeCreate 和 created 添加了setup
方法名称发生变化:方法名称前面多了个on,中间是驼峰式的
同一个生命周期可以触发多次 卸载组件的生命周期变化:onBeforeUnmount onUnmounted
vue3组合API数据响应式的方法
ref和reactive:
说明:ref和reactive都具有使数据响应式功能,什么时候用哪个呢?
个人理解 :ref 一般使用在基本数据类型中 引用数据类型也可以用 (ref使用数据类型会在底层去转换为reactive)
reactive:使用在引用数据类型中 但是如果重新赋值就会失去响应的能力 此时就应该用ref
<template>
import { reactive, ref } from "vue";
<div>
{{name}}
<button @click="changText">点击改变值</button>
</div>
</template>
<script setup>
const name = '张三' //此处的数据并不是响应式的
const people1 = reactive({
name:'李四',
like:{
play:'篮球'
}
})
const people2 = ref('王五')
const changText = () =>{
//我们点击之后更改people2的值
people2.value = '赵六'; //ref声明的响应数据都必须.value才能拿到值
//我们点击之后更改people1的爱好为游泳
#写法1
people1.like.play = '游泳' //reactive 声明的对象都为响应式
#写法2
people1.like = {paly = '游泳'}
#错误写法
people1 = {name:'李四',like:{paly:'游泳'}} // 此时就是相当于重新给people1赋值,不能允许这样做,会报错 此刻可以改为 people1 = ref({...})的写法
}
</script>
toRef和toRefs
说明:这两个方法都是使数据变成响应式
const obj = {
msg:'你好',
info:'我很假'
}
const msg =toRef( obj,'msg')
const { msg, info } = toRefs ( obj )
#使用后,不会影响原来的对象 会生成一个新的响应数据 类似es6的解构赋值
计算属性computed
<template>
<div>
{{numadd}}
</div>
</template>
<script setup>
import { computed } from "vue";
// 计算属性
let num = ref(0);
const numadd = computed(()=> {
num.value++;
return num.value; //computed变成了一个回调函数 必须要有返回值
});
</script>
监听属性watch
watch有三个参数:
参数1:监听的参数 参数2:监听的回调函数 参数3:监听的配置(immediate)
<template>
import { reactive, ref, watch } from "vue";
<div>
{{name}}
<button @click="changText">点击改变值</button>
</div>
</template>
<script setup>
const people1 = reactive({
name:'李四',
like:{
play:'篮球'
}
})
const num = ref(2)
const people2 = ref('王五')
const changText = () =>{
//我们点击之后更改people2的值
people2.value = '赵六'; //ref声明的响应数据都必须.value才能拿到值
//我们点击之后更改people1的爱好为游泳
people1.like.play = '游泳'
}
//监听单个数据
watch(people2,(newValue,oldValue)=>{
console.log(newValue,oldValue)
})
/*
若watch监视的是reactive定义的响应式数据,则无法正确获得oldvalue!
若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
*/
watch(reactive,(newValue,oldValue)=>{
console.log(newValue,oldValue)
},{immediate:true,deep:false})
//监听多个数据
watch([num,people2],(newValue,oldValue)=>{
console.log(newValue,oldValue)
})
//监听reactive中的一个属性
watch(()=>people.like.play,(newValue,oldValue)=>{
console.log(newValue,oldValue)
})
//监听reactive中的一个嵌套对象
//此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
watch(()=>people.like,(newValue,oldValue)=>{
console.log(newValue,oldValue)
},{immediate:true,deep:true})
</script>
vue3组件传值方法
父传子(props)(一般写法)
`父组件`
<PropCmpt :title="'第一个prop'" />
`子组件`
<p>{{title}}</p>
export default defineComponent({ //defineComponent中使用props属性,需要规定其类型
props: {
title: String,
},
setup() {
return {};
},
});
子传父($emit)(一般写法)
//直接在点击事件时,使用$emit 定义自定义事件和传值
<button @click="$emit('do-sth', msg)">点击触发自定义事件</button>
//仍然需要在下面去注册使用
export default defineComponent({
emits: ["do-sth"],
setup() {
const msg = ref<string>("这是自定义事件传递的值");
return {
msg, //此处为传递的数据 可以在上面事件中直接写数据
};
},
});
#或
<button @click="clickFunc">点击触发自定义事件</button>
export default defineComponent({
setup(props,context) {
const msg = ref<string>("这是自定义事件传递的值");
const clickFunc = ()=>{
context.emit('do-sth',msg)
}
return {
};
},
});
父传子(props)(语法糖写法)
在语法糖中没有地方能写props 因此有了defineProps(此处没有介绍ts语法 因为更复杂 还包含了容器概念)
`父组件`
<PropCmpt :title="'第一个prop'" />
`子组件`
<p>{{props.title}}</p>
<script setup>
const props = defineProps({
title:{
type:String,
}
})
</script>
子传父($emit)(语法糖写法)
<template>
<div>
<button @click="sendToFather">点我给父组件传递参数</button>
</div>
</template>
<script setup>
import { ref } from "vue";
const val = ref("我是子组件传递过来的参数");
const emit = defineEmits(["do-sth"]); //需要先去注册才能使用
const sendToFather = () => {
emit("do-sth", val.value);
};
</script>
<style scoped>
</style>
兄弟组件通信(此处运用插件mitt)仿BUS通信
先安装插件:yarn add mitt -S
在根目录下创建BUS目录,
index.ts
// 引入mitt
import mitt from 'mitt'
// 默认导出mitt调用结果
export default mitt()
在发送组件中 Brother.vue
引入导出的mitt
//触发事件后发送数据
import BUS from '....'
setup() {
function sendData() {
BUS.emit("sendToBrother", "这是大哥发的数据");
}
}
在接收组件中LittleBrother
引用导出的mitt
<p>{{text}}</p>
import BUS from '....'
setup() {
let text = ref<string>('')
return {text};
},
mounted(){
BUS.on("sendToBrother", (data) => {
console.log(data);
this.text = data
});
}
vue3挂载全局方法
globalProperties和provide
个人理解:这两方法都能全局挂载,但是,网络上说第一个使用可能会导致打包路径错误或者丢失。所以我一般用第二个。 provide 用法是祖组件给孙子组件传参。可以用在全局而已
const app = createApp(App)
app.config.globalProperties.$utils = utils
//在页面中使用
import { getCurrentInstance } from 'vue'
let { proxy } =getCurrentInstance() //getCurrentInstance()用于获取当前组件的上下文
console.log(proxy.$utils);
}
const app = createApp(App)
app.provide('$utils',utils)
//在页面使用
import { inject } from 'vue'
let utils = inject('utils')
vue3其他属性
在vue3中新增了对数据描述的属性(知道有就行)
-
shallowReactive
与shallowRef
-
readonly
与shallowReadonly
-
toRaw
与markRaw
-
customRef
-
响应式数据的判断
isRef: 检查一个值是否为一个 ref 对象
isReactive: 检查一个对象是否是由 reactive 创建的响应式代理
isReadonly: 检查一个对象是否是由 readonly 创建的只读代理
isProxy: 检查一个对象是否是由 reactive 或者 readonly 方法创建的代理