【一】vue3介绍
# 1 vue2的所有东西,vue3都兼容
# 2 vue3 不建议使用vue2的写法--》配置项API
# 3 vue3 :选项式 API 和组合式 API
-选项式:配置项:就是vue2的写法
export default{
data(){
return {}
},
methods:{}
}
-组合式 :
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
function add(){
}
2.1快速体验组合式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue3/vue.js"></script>
</head>
<body>
<div id="app">
<h1>组合式快速体验</h1>
{{name}}
<button @click="handleping">组合式</button>
</div>
</body>
<script>
let app = Vue.createApp({
setup() {
const name = Vue.ref("llh")
function handleping() {
alert("组合式")
}
return {name, handleping}
}
})
app.mount("#app")
</script>
</html>
2.2快速体验配置项
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue3/vue.js"></script>
</head>
<body>
<div id="app">
<h1>选项式</h1>
{{name}}
<button @click="handleAdd">选项式</button>
<h1>组合式快速体验</h1>
{{name}}
<button @click="handleping">组合式</button>
</div>
</body>
<script>
let app = Vue.createApp({
data() {
return {name: 'llh'}
},
methods: {
handleAdd() {
alert("点到楼")
}
}
})
app.mount("#app")
</script>
</html>
2.3拥抱ts
# 1 之前写vue2用js
# 2 vue3-->ts-->微软推出的--》最终要被编译成js才能运行在浏览器中
-使用ts写,可以避免很大错误
-ts是js的超集---》ts完全兼容js
# 3 我们学的是
vue2+js+vue-router+vuex+elementui
vue3+js+vue-router+pinia+elementui-plus
# 4 变化
新的生命周期钩子
data 选项应始终被声明为一个函数
移除keyCode支持作为 v-on 的修饰符
【二】vue3快速创建项目
2.1使用vue-cli创建
# 跟之前几乎一样
重新选择自定义配置项要选vue3.x
2.2使用vite创建(推荐)
#1 什么是vite?—— 新一代前端构建工具。
优势如下:
开发环境中,无需打包操作,可快速的冷启动。
轻量快速的热重载(HMR)。
真正的按需编译,不再等待整个应用编译完成。
# 2 兼容性注意
Vite 需要 Node.js 版本 18+,20+。然而,有些模板需要依赖更高的 Node 版本才能正常运行,当你的包管理器发出警告时,请注意升级你的 Node 版本
官网:https://cn.vitejs.dev/
# 3 镜像源
# 配置npm镜像站:npm config set registry https://registry.npmmirror.com
# 查看镜像站:npm config get registry
#4 创建
# 创建项目方式一
npm create vite@latest
# 创建项目方式二:指定名字
npm create vite@latest vue3_demo002
# 创建项目方式三
cnpm create vite@latest vue3_demo002
# 创建项目方式四
cnpm create vite vue3_demo002
# 3 使用编辑器打开vue3项目
# 4 安装依赖
npm install
# 5 运行项目
npm run dev
2.3使用不同工具创建的项目启动命令不同
#看package.json中的配置
#1 运行vue项目时,执行的命名
# npm run serve
# npm run dev
# 2 对应的是package.json中
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
【三】常用api
3.1定义变量统一用const
1 const是常量--》不允许变的
2 咱们用 ref包裹后,是个对象,虽然对象是常量,对象不能变,对象.value可以变化
3 之所以定义成const原因是,后期不能修改对象 【对象.value可以改】
4 如果用let声明 ,后期修改对象不会报错,会失去响应式,导致程序出问题,
3.2 以后代码都写在setup函数中-->组合式
# 组合式和配置项能不能混用?
-可以混用
-并且在配置项api的方法中,可以拿到setup函数中定义的变量
-以后只用一种
-配置项
-组合式(推荐的)
"""注意:setup函数的执行比那些生命周期都先的,所以混用注意,但是不建议混用"""
3.3setup函数
1.如果使用配置项API---》写起来跟vue2一样
2.如果写组合式API---》所有代码都要写在setup函数中
-后期除了setup函数,其他都不带了
3.setup函数必须返回变量或函数--》在template中才能使用
4.默认不带响应式,需要使用ref或reactive包裹
3.3.1setup函数的组合式API示例
<template>
<h1>setup示例</h1>
{{name}}
<button @click="toGGbone">点我变身GGbone</button>
</template>
<script>
import {ref} from 'vue'
export default {
name: "SetupDemoView",
setup(){
const name=ref("llh")
const toGGbone=()=>{
name.value='GGbone~'
}
return{
name,
toGGbone
}
}
}
</script>
<style scoped>
</style>
3.4ref
1 ref 包裹值类型[数字,字符串,布尔],做成响应式
2 reactive包裹引用类型[对象,数组],做成响应式
3 使用reactive包裹的对象,直接通过 . [] 取值赋值就是响应式的-->因为他会有一个proxy代理变成了类似于对象的直接取值即可
ref包裹的对象,需要使用 对象.value 修改值
4 使用ref包裹的,在template中,不用使用 变量.value---》记住在模板中和我们在vue2 中一样用就行
# 1 用于包裹 值 【数字,字符串,布尔】类型变量,使其具有响应式的类
const count = ref(0)
count.value
3.5reactive
# 1 用于包裹 引用 【数组,对象】类型变量,使其具有响应式的类
const user_info = reactive({name: 'lqz', age: 19})
# 使用时,不需要 对象.value-->因为它是个代理对象
user_info.age++
3.6 计算属性
3.6.1写一个关于姓与名和全名组合输入框双向变化的案例
<template>
<h1>写一个关于姓与名和全名组合输入框双向变化的案例</h1>
<p><input type="text" v-model="pre_name"></p>
<p><input type="text" v-model="last_name"></p>
<p><input type="text" v-model="full_name"></p>
</template>
<script>
import {computed,ref} from "vue";
export default {
name: "ComputeDemo",
setup(){
const pre_name=ref('')
const last_name=ref('')
const full_name=computed({
get(){
return pre_name.value+last_name.value
},set(values){
pre_name.value=values.slice(0,1)
last_name.value=values.slice(1)
}
})
return{
pre_name,
last_name,
full_name
}
}
}
</script>
<style scoped>
</style>
3.7监听属性
3.7.1监听值类型,监听对象类型,监听多个变量
<template>
{{ name }}
<button @click="toGGbone">点我变身GGbone</button>
{{ age }}
<button @click="changeage">点我变年轻</button>
<button @click="doublechange">点我双变</button>
</template>
<script>
import {ref, watch, reactive} from "vue";
export default {
name: "WatchView",
setup() {
const name = ref("llh")
const age = ref(99)
// const toGGbone = () => {
// name.value = 'GGbone~'
// }
#监听值
// watch(name, (newValue, oldValue) => {
// console.log('height变化了', newValue, oldValue)
// })
#监听对象
// const p = reactive({age: 100, hobby: '变身'});
//
// const changeage = () => {
// p.age--;
// };
//
#注意这里的第一个参数是一个函数
// watch(() => p.age, (newValue,oldValue) => {
// console.log('年轻了', newValue, oldValue);
// });
#监听多个值---》是值数组
const changeage = () => {
age.value--;
};
const toGGbone = () => {
name.value = 'GGbone~'
}
const doublechange = () => {
name.value = 'GGbone~'
age.value--;
}
#第一个参数是一个数组
watch([name, age], (newValue, oldValue) => {
console.log('变了', newValue, oldValue);
});
return {
name,
age,
toGGbone,
changeage,
doublechange
}
}
}
</script>
<style scoped>
</style>
3.7.2watchEffect函数
1. 当页面重新加载时,setup 函数会再次被调用,因此 watchEffect 也会再次被定义并立即执行一次以收集依赖项
2. watchEffect内部用了某个变量,某个变量发送变化,就会触发
# 如果两个同时都变化,只会执行一次
watchEffect(() => {
const x1 = sum.value
const x2 = person.name
console.log('watchEffect配置的回调执行了')
})
【四】生命周期
# vue2中8个生命周期钩子
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeDestroy
destroyed
# vue3中8个生命周期钩子---》配置项API
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted
# vue3 组合式api的生命周期钩子
beforeCreate===>setup()-->这时候是没有data了,所以是在变量定义前
created=======>setup()-->这时候是有data了,所以是在变量定义后--》定义变量写在变量里
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted
4.1vue3的配置项api生命周期钩子
4.2vue3的组合式生命周期钩子
<template>
<h1>生命周期组件</h1>
{{ name }}
<button @click="toGGbone">点我变身GGbone</button>
</template>
<script>
import {ref, watch,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted} from "vue";
export default {
name: "LifeView", setup() {
// 组合式api写法
// 1 组件还没有创建时候执行:beforeCreate
console.log('beforeCreate')
// 2 组件创建完成执行:created--》跟后端交互拿数据
const name = ref('llh')
// axios.get().then(res=>{
// name=res.data.name
// })
const toGGbone = () => {
name.value = 'GGbone~'
}
console.log('created')
watch(name, (newValue, oldValue) => {
console.log('年轻了', newValue, oldValue);
});
//3 beforeMount-->onBeforeMount
// onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted
onBeforeMount(() => {
console.log('onBeforeMount', '组件挂载前')
})
//4 mounted-->onMounted
onMounted(() => {
console.log('onMounted', '组件挂载后')
})
//5 beforeUpdate-->onBeforeUpdate
onBeforeUpdate(() => {
console.log('onBeforeUpdate', '更新之前')
})
//6 updated-->onUpdated
onUpdated(() => {
console.log('onUpdated', '更新之后')
console.log(name.value)
})
//7 beforeUnmount-->onBeforeUnmount
onBeforeUnmount(() => {
console.log('onBeforeUnmount', '销毁之前')
})
//8 unmounted-->onUnmounted
onUnmounted(() => {
console.log('onUnmounted', '销毁后')
})
return {toGGbone, name}
}
}
</script>
<style scoped>
</style>
4.2.1补充,watch先执行还是onBeforeUpdate先
watch先
update是刷新完了,但是watch是属性一变化就触发
【五】setup的特殊写法
# 1 vue3中之前写组合式的组件写法
export default {
name: 'HomeView',
setup() {
}
}
"""####重点####与之前写法不同的地方"""
1 组件,只需要导入,就会自动注册,必须带后缀名 vue
2 setup写法
<script setup> 写原来setup函数中的代码即可,就是完全js的写法</script>
3 生命周期钩子--beforeCreate,created,on。。。。
4 监听属性,计算属性
5 组件间通信 父传子
# 父组件中:跟之前一样
<HelloWorld :msg="msg"></HelloWorld>
# 子组件中:
defineProps({
msg: String,
})
6 组件通信,子传父
-父组件中:
# html
<HelloWorld @send="handleReceive"></HelloWorld>
<p>父组件中得name:{{name}}</p>
# js
<script setup>
const name = ref('')
function handleReceive(a){
name.value=a
}
</script>
-子组件中:
# js
let $emit = defineEmits(['send']) # 等同于之前的 this.$emit
const name =ref('')
const handleSend=()=>{
$emit('send',name.value)
}
# html
<input type="text" v-model="name">-->{{name}}
<br>
<button @click="handleSend">点我传给父亲</button>
# 7 插槽
# 8 mixin 没了-->直接导入导出用
# 9 插件一样
# 10 toRefs-->把对象中所有变量都做成响应式
# 11 toRef -->只把对象中某一个做成响应式
# 12 ref属性
5.1子传父父传子
5.1.1父组件
<template>
<p >{{age}}</p>
<h1>父组件</h1>
<HelloWorld :msg="msg" @senddata="getdata"></HelloWorld>
</template>
<script setup>
import HelloWorld from "@/components/HelloWorld";
import {ref} from "vue";
const msg=ref("哟呼🎶🎶🎶")
const age=ref('')
const getdata=(s)=>{
age.value=s.value
}
</script>
<style scoped>
</style>
5.1.2子组件
<template>
<div class="hello">
<h1>子组件拿到的:{{ msg }}</h1>
子组件的{{age}}
<button @click="senddata">传给爹</button>
</div>
</template>
<script setup>
import {ref} from "vue";
defineProps({
msg: String,
})
const age=ref(111)
let $emit = defineEmits(['send'])
const senddata=()=>{
$emit('senddata',age)
}
</script>