前端:Vue3学习
-
- [1. 打包发布](#1. 打包发布)
- [2. vue3 项目构建](#2. vue3 项目构建)
- [3. vue3- setup选项](#3. vue3- setup选项)
- [4. vue3 ->reactive 和 ref函数--响应式数据](#4. vue3 ->reactive 和 ref函数--响应式数据)
- [5. vue3 computed-计算属性](#5. vue3 computed-计算属性)
- [6. vue3 watch 监听数据变化](#6. vue3 watch 监听数据变化)
- [7. vue3 生命周期 - 选项式&组合式](#7. vue3 生命周期 - 选项式&组合式)
- [8. vue3 组件通信](#8. vue3 组件通信)
- [9. vue3 模板引用&defineExpose](#9. vue3 模板引用&defineExpose)
- [10. vue3 provide & inject 多层组件数据通信](#10. vue3 provide & inject 多层组件数据通信)
1. 打包发布
(vue2或vue3)打包的作用:
- 将多个文件压缩合并成一个文件
- 语法降级
- less scss ts 语法解析
打包后,可以生成浏览器能够直接运行的网页
打包命令为:yarn build
执行上述命令之后,在项目的根目录会自动创建一个文件夹dist ,dist中的文件就是打包后的文件,只需要放到服务器即可。
默认情况下,需要放到服务器根目录打开,如果希望双击运行,需要配置publicPath 配成相对路径。在vue。config.js中进行配置
在项目根目录下运行打包命令:
在项目根目录下生成dist文件夹:
配置publicPath:
打包之后直接运行dist文件夹下的index.html即可
打包优化 ,路由懒加载,当打包构建应用时,js包会变得非常大,影响页面加载。如果把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。
在路由配置文件修改对应组件导入方式,如下:
js
import Login from "@/views/login/Login.vue"
// 旧的导入方式
const Login = ()=> import('@/views/login/Login.vue')
// 异步组件方式
2. vue3 项目构建
vue2为选项式api,而vue3属于组合式api
创建vue3项目,需要node版本为16及以上
js
npm init vue@latest
执行上述命令之后,在浏览器输入对应地址,如下:
3. vue3- setup选项
vue文件,首先是script,然后是template,最后是style。
在script上写上setup,用于指定当前支持组合式api
- setup执行时机比beforeCreate还早;
- setup行数中,获取不到this;
- 数据和函数,需要在setup最后return,才能在模板中进行应用;
html
<script>
export default{
setup(){
console.log('setup',this)
const hello = 'hello world'
const hh = function(){
console.log(hello)
}
return {
hello,
hh
}
},
beforeCreate(){
console.log('beforecreate')
}
}
</script>
<template>
<div>
{{ hello }}
</div>
<button @click="hh">
hh
</button>
</template>
使用setup语法糖简化代码。
html
<script setup>
const hello = 'hello world'
const hh = function(){
console.log(hello)
}
</script>
<template>
<div>
{{ hello }}
</div>
<button @click="hh">
hh
</button>
</template>
4. vue3 ->reactive 和 ref函数--响应式数据
使用reactive,数据必须是以对象的形式,返回的是一个响应式对象。
html
<script setup>
import { reactive } from 'vue';
const state = reactive({
count:100
})
const add = ()=>{
state.count ++;
}
</script>
<template>
<div>
{{ state.count }}
</div>
<button @click="add">
加1
</button>
</template>
使用ref 可以接收简单类型或复杂类型的数据,返回一个响应式的对象。本质原有传入数据的基础上,外层包了一层对象,包成了复杂类型,再借助reactive实现的响应式。
需要注意的是,脚本中访问数据,需要通过".value"进行访问或修改;在template中,".value"不需要添加。
html
<script setup>
import { ref } from 'vue';
const count = ref(100);
const add = ()=>{
count.value ++;
}
</script>
<template>
<div>
{{ count }}
</div>
<button @click="add">
加1
</button>
</template>
运行结果:
5. vue3 computed-计算属性
引入及使用:
js
import { computed} from 'vue';
const getData = computed(()=>{
return '计算属性的逻辑'
})
html
<script setup>
import { ref ,computed} from 'vue';
const arr = ref([1,2,3,4,5,6,7,8,9,10]);
// 声明数据
const getData = computed(()=>{
return arr.value.filter(x=>x>3)
})
</script>
<template>
<div>
{{ arr }}
</div>
<div>
{{ getData }}
</div>
</template>
6. vue3 watch 监听数据变化
监听一个或者多个数据的变化,数据变化时执行回调函数.
两个额外参数:1. immediate(立即执行)2. deep(深度监听)
js
// 监视单个数据
watch(数据名,(newValue,oldValue)=>{
// 代码逻辑
})
// 监视多个数据
watch([数据名1,数据名2],(newValueArr,oldValueArr)=>{
// 代码逻辑
})
参考代码如下:
html
<script setup>
import {ref,watch} from 'vue';
const name = ref('张三丰')
const count = ref(0)
const change_name = ()=>{
name.value = '张三'
}
const change_count = ()=>{
count.value = 1
}
watch(name,(new_v,old_v)=>{
console.log(new_v,old_v)
})
watch([count,name],(new_arr,old_arr)=>{
console.log(new_arr,old_arr)
})
</script>
<template>
<div>
<p>{{ count }}</p>
<p>{{ name }}</p>
</div>
<div>
<button @click="change_name">改name</button>
<button @click="change_count">改count</button>
</div>
</template>
运行结果:
深度监听,当监听的数据类型为对象时,此时如果直接监听这个对象数据,需要添加深度监听的配置,否则修改这个对象下的某个属性时并不会触发这个监听。
html
<script setup>
import { ref, watch } from 'vue';
const user = ref({
name: 'zs',
age: 18
})
const change_user_name = () => {
user.value.name = 'zsf'
}
watch(user, (newValue, oldValue) => {
console.log(newValue, oldValue)
},{
deep:true
})
</script>
<template>
<div>
{{ user }}
</div>
<div>
<button @click="change_user_name">修改</button>
</div>
</template>
但是如果采用深度监听又会存在一个问题,因为它是监听这个对象及对象下的所有属性,如果只需要监听对象下的某个属性的变化,此时采用下述监听方式,如下:
html
<script setup>
import {ref,watch} from 'vue';
const user = ref({
name:'zs',
age:18
})
const change_user_name = ()=>{
user.value.name = 'zsf'
}
watch(()=>user.value.name,
(newValue,oldValue)=>{
console.log(newValue,oldValue)
})
</script>
<template>
<div>
{{ user }}
</div>
<div>
<button @click="change_user_name">修改</button>
</div>
</template>
7. vue3 生命周期 - 选项式&组合式
vue3中关于生命周期支持选项式和组合式
vue3的生命周期api(选项式和组合式)
选项式 | 组合式 |
---|---|
beforeCreate/created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
html
<script setup>
import { onMounted } from 'vue';
onMounted(()=>{
console.log('mounted生命周期函数1')
})
onMounted(() => {
console.log('mounted生命周期函数2')
})
</script>
<template>
</template>
8. vue3 组件通信
父传子 ,父组件中给子组件绑定属性,子组件内部通过defineProps编辑器宏选项进行接收。
子传父,在子组件内部,emit触发时间(defineEmits编译器宏获取emit),在父组件中通过@监听。
父组件
html
<script setup>
import {ref} from 'vue'
import sonCom from '@/components/son-com.vue'
const name = ref('张三丰')
const changeName = (v)=>{
name.value += '&' + v
}
</script>
<template>
<div class="father">
<h3>父组件</h3>
<p>{{ name }}</p>
<sonCom :name="name" @change-name="changeName"></sonCom>
</div>
</template>
<style>
.father{
width: 220px;
height: 220px;
border: 1px solid blue;
}
</style>
子组件
html
<script setup>
const props = defineProps({
name:String
})
const emit = defineEmits(['change-name'])
console.log(props.name)
const change_name = ()=>{
emit('change-name','张三丰')
}
</script>
<template>
<div class="son">
<p>我是子组件</p>
<p>{{ name }}</p>
<button @click="change_name">修改</button>
</div>
</template>
<style>
.son{
border: 1px solid red;
width: 140px;
height: 140px;
}
</style>
子组件中在脚本中使用父组件传递过来的数据,需要使用props.数据名 ;在模板中渲染时直接使用数据名即可。
9. vue3 模板引用&defineExpose
模板引用步骤,通过ref函数,生成一个ref对象;通过ref表示,进行绑定;通过ref对象.value即可访问到绑定的元素(必须渲染完才可以进行绑定)。
获取模板引用必须在组件挂载完毕之后才行,通常可以在onMounted回调函数内部进行使用或者一些点击按钮的点击事件(点击事件都可以触发了,那么说明模板已经渲染完毕了,此时可以操作dom元素)。
父组件
html
<script setup>
import {ref} from 'vue'
import sonCom from './components/son-com.vue';
import { onMounted } from 'vue';
const divRef = ref(null)
const changeStyle = ()=>{
const div = divRef.value
div.style.fontFamily = '华文宋体'
}
const divRef2 = ref(null)
onMounted(()=>{
console.log(divRef2.value)
})
</script>
<template>
<div ref="divRef">
张三丰
</div>
<button @click="changeStyle">
修改演示
</button>
<sonCom ref="divRef2"></sonCom>
</template>
子组件
如果在父组件中需要使用子组件的数据和方法,需要使用编译宏defineExpose进行暴露,否则不能引用到。
html
<script setup>
const data = 100
const get_data = ()=>{
console.log(data)
}
defineExpose({
data,
get_data
})
</script>
<template>
<div class="son">
<p>我是子组件</p>
<button @click="get_data">获取数据</button>
</div>
</template>
<style>
.son{
border: 1px solid red;
width: 140px;
height: 140px;
}
</style>
10. vue3 provide & inject 多层组件数据通信
在顶层组件中使用provide把数据传递下去,在底层组件中使用inject中进行接收,接收的可以是数据、响应式数据、方法。
顶层组件
html
<script setup>
import sonCom from '@/components/son-com.vue'
import { provide, ref } from 'vue';
const count = ref(100)
provide('count',count)
const add = ()=>{
count.value ++
}
provide('add',add)
</script>
<template>
<div>
<p>顶层组件</p>
<sonCom></sonCom>
<button @click="add">修改</button>
</div>
</template>
中间组件
html
<script setup>
import sonSCom from '@/components/son-s-com.vue'
</script>
<template>
<div>
<p>中间组件</p>
<sonSCom></sonSCom>
</div>
</template>
底层组件
html
<script setup>
import { inject } from 'vue';
const count = inject('count')
const add = inject('add');
</script>
<template>
<div>
<p>底层组件</p>
<span>{{ count }}</span>
<br>
<button @click="add">底层组件按钮</button>
</div>
</template>