开篇闲扯: 怎么说,回头看看,至今至此,从上家主动离职换工作已经5个多月,差1个月转正,很庆幸能进入这个公司,也很苦恼,庆幸的是在大环境不好的情况下我能在2周内找到工作,进入这里发点小余光,发点小热,贡献一下自己的微薄力量;苦恼啥,我天性乐观不爱被束缚,对新鲜事物接受能力比较强,公司内部的调整吧,不便多说,我总感觉我这单纯的前端开发岗位岌岌可危,比较焦虑吧;我始终坚持:爱情可以没有,但工作必须有。可能是性格原因,也可能是工作后的成长吧。我单身过的也不错,很潇洒;有对象的时候只能说是锦上添花吧。工作伴随着自己一天80%的时间吧,成年人不可缺少的东西,每次走到杭师大校区那,看到他们的学生总会心生羡慕,羡慕什么,我也说不上来,可能是羡慕他们青春年少,羡慕他们无忧无虑不必为了工作赚钱的事情苦恼,也可能是羡慕他们只需要对学习有压力,无需考虑更多吧...
咋说呢,最开始我讨厌工作,拒绝成长,没去实习,选择了考研,计算机的全日制是真tn的难啊,高数考了10几分,我果断放弃,加入了打工人的队伍,从上班到现在给我弟买过一个苹果手机,买电脑的时候给他拿了2k,上专升本的培训班给他拿了2k,平时也会给他点零花钱都是小钱几百几百;给我妈妈灭个月会打钱,不多让她补贴家用跟我爸爸俩人用,家里租房拿了2k。我妹妹结婚拿了1w,生外甥女1k,外甥女金手镯我添4k,买个礼物3k。其他想不起来了,七七八八吧,就恁些。有前真好,不得不说,从前小时候没钱的时候感觉爸妈都被人看轻了,现在没人敢这样对他们,家里拆迁也赔了不少,我妹新婚给了10w,彩礼全拿走。很感谢父母没有重男轻女,也很感谢他们从小一直陪在身边,让我们不是留守儿童。小时候穷,但很快乐,父母陪着,每天最开心的是他们回家给带好吃的哈哈哈。不多说咯,这篇是我库存,顺便改了一些东西,小小总结,一起看看vue3吧,日常小结,轻喷。
1-v3组合式API
v3组合式API(composition API)主要用于在大型组件中提高代码逻辑的可复用性;传统的组件随着业务复杂度越来约高,代码量会不断增加,整个代码逻辑都不易阅读和理解。 v3使用组合式API的地方为setup。
在setup中,我们可以按逻辑关注点对部分代码进行分组,然后提取逻辑片段并与其他组件共享代码。因此组合式API允许我们编写更有条理的代码。
与传统的API对比, vue2中使用的optionAPI: 全局API
scss
Vue.use(plugin) // 安装插件
Vue.extend() // 创建"子类",参数是一个包含组件选项的对象
Vue.nextTick(() => {}) // 在下次DOM更新循环结束之后执行延迟回调
Vue.set(target,index/propertyName, value) // 添加响应式新属性
Vue.directive('my-directive', {})// 注册自定义指令
Vue.filter('my-filter', ()=>{}) // 注册全局过滤器
Vue.component('my-component', {}); // 注册全局组件
Vue.mixin(object) // 注册全局混入
Vue.observable() // 让一个对象可响应
vue2中常用的API
go
`Vue.component(name, options)`:用于注册全局组件。
`Vue.directive(name, definition)`:用于注册全局指令。
`Vue.filter(name, definition)`:用于注册全局过滤器。
`new Vue(options)`:用于创建一个Vue实例。
`vm.$mount(element)`:手动挂载Vue实例到一个元素上。
`vm.$data`:访问Vue实例的数据对象。
`vm.$props`:访问Vue实例的props数据。
`vm.$options`:访问Vue实例的配置项。
`vm.$emit(event, [...args])`:触发当前实例上的自定义事件。
`vm.$on(event, callback)`:监听当前实例上的自定义事件。
`vm.$nextTick(callback)`:在DOM更新之后执行回调函数。
`vm.$watch(expOrFn, callback, [options])`:观察Vue实例上的数据变化。
vue2中的生命周期函数
arduino
beforeCreate //实例初始化完成,但是各配置还未进行
created // watch\method\computed已被配置完成,但未进行挂载
beforeMounted // 挂载之前,render首次被调用
mounted // 已挂载完成,但是不能保证子组件都渲染完成,如果需要可以调用nextTIck
beforeUpdate // 数据发生改变,DOM被更新之前调用
updated // 数据改变导致虚拟DOM重新渲染和更新后被调用,也同样不能保证子组件都渲染完成
activated // 被缓存的组件激活时调用
deactivated // 被缓存的组件失活时被调用
beforeDestroy // 实例销毁前使用
destroyed // 实例销毁后
vue3与vue2中生命周期函数的不同之处
beforeCreate和created:Vue 2和Vue 3中的beforeCreate和created生命周期函数没有变化,仍然用于实例初始化之前和之后的逻辑。
beforeMount和mounted:Vue 2和Vue 3中的beforeMount和mounted生命周期函数也没有变化,分别在模板编译挂载之前和之后被调用。
beforeUpdate和updated:在Vue 2中,beforeUpdate和updated生命周期函数在组件数据更新时被调用。而在Vue 3中,这两个生命周期函数被合并到一个新的生命周期函数中,称为beforeUpdate。
beforeDestroy和destroyed:在Vue 2中,beforeDestroy和destroyed生命周期函数分别用于实例销毁之前和之后的逻辑。在Vue 3中,这两个生命周期函数被重命名为beforeUnmount和unmounted。
新增的生命周期函数:Vue 3引入了一些新的生命周期函数,用于更精确地控制组件行为。这些新的生命周期函数包括:beforeUnmount(替代beforeDestroy)、unmounted(替代destroyed)、onRenderTracked、onRenderTriggered等。
需要注意的是,Vue 3还使用了新的Composition API,提供了setup函数来替代Vue 2中的created和beforeMount生命周期函数,使得组件的逻辑更加清晰和可组合。同时,Vue 3还引入了Suspense和Teleport等新特性,以及更好的TypeScript支持。
vue3常见的生命周期函数
scss
setup()开始创建组件之前执行的
onBeforeMount() 组件挂载到节点上之前执行的函数
onMounted() 组件挂载完成后执行的函数
onBeforeUpdate() 组件更新之前执行的函数
onUpdated() 组件更新完成之后执行的函数
onBeforeUnmonut() 组件卸载之前执行的函数
onUnmounted 组件卸载后执行的函数
onActivated() 生命周期钩子函数被激活时执行
onDeactivate 从A组件切换到B组件 A组件消失时执行
总结:
-
v3组合式api取消了beforeCreated和created钩子函数,使用setup钩子代替,且里面不能使用this。
-
v3的组合式API生命周期函数要比v2选择式API的生命周期多个前缀on,而且要import单独引用。
2 关于v3中一些重点API
2.1--setup函数
- setup是v3中的一个全新的配置项,值为一个函数;
- setup是所有CompositionAPI(组合API)的基础,组件中所用到的数据、方法等都需要在setup中进行配置;
- setup函数在组件创建created()之前执行,setup函数接收两个参数props,context。
- 参数1-props:响应式的,当传入新的prop时,它将被更新;
- 参数2:context是一个普通的js对象,它是一个上下文对象,暴露了其它可能在 setup 中有用的值。
setup的两个注意点:
1、setup执行时机,在beforeCreate之前执行一次,this是undefined;
2、setup的参数:
- props:指为对象,包含组件外部传递过来,且组件内部声明接收了的属性。
- context:上下文对象
- attrs:值为对象,包含组件外部传递过来,但没有在props配置中声明的属性,相当于this.$attrs;
- slots:收到的插槽内容,相当于this.$slots;
- emit:分发自定义事件的函数,相当于this.$emit。
注意: 在 setup 中你应该避免使用 this,因为它不会找到组件实例。setup 的调用发生在 data property、computed property 或 methods 被解析之前,所以它们无法在 setup 中被获取。
2.2--ref
v3中可以通过一个新的ref函数使任何响应式变量在任何地方起作用 ref()函数可以根据给定的值来创建一个响应式的数据对象,返回值是一个对象,且只包含一个.value属性。 在setup()函数内,由ref创建的响应式数据返回的是对象,所以需要用.value来访问。
2.3--reactive
v3中,可以使用reactive函数来创建一个响应式的数据对象,reactive函数接收一个普通的js对象,并返回一个响应式的代理对象。 下面是一个使用reactive函数创建响应式数据的例子:
javascript
import { reactive } from 'vue';
const state = reactive({
message:'hello v3',
count:0
});
console.log(state.message); //输出:hello v3
console.log(state.count); //输出 0
state.message = 'hello world';
state.count++;
console.log(state.message); //输出: Hello World
console.log(state.count); //输出:1
在上面的例子中,我们使用reactive
函数创建了一个响应式的state
对象。这个对象中包含了两个属性message
和count
。我们可以像访问普通对象一样访问和修改state
对象的属性。但是,由于state
对象是响应式的,当我们修改属性的值时,与之相关的视图会自动更新。
需要注意的是,reactive
函数只会对对象的第一层属性做响应式处理,而不会对嵌套对象进行深度响应式处理。如果你需要对嵌套对象进行响应式处理,可以使用ref
或toRef
函数。另外,reactive
函数也可以用于创建响应式的数组。
总结一下,Vue 3中的reactive
函数可以用于创建响应式的数据对象,你可以像访问普通对象一样访问和修改响应式对象的属性,并且与之相关的视图会自动更新。
2.4--ref和reactive的区别和对比
1-从定义数据角度对比:
- ref用来定义:基本数据类型;
- reactive用来定义:对象(或数组)类型数据;
2-从原理角度对比:
- ref通过Object.defineProperty()的get和set来实现响应式;
- reactive通过使用Proxy来实现响应式(数据劫持),并通过Reflect操作源对象内部的数据。
3-使用角度对比:
- ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value;
- reactive定义的数据:操作数据与读取数据均不需要.value;
4-数据结构对比:
ref
函数用于创建单个数据的响应式引用。它将数据包装在一个内部对象中,并返回这个对象的引用。所以当你访问ref
创建的响应式变量时,需要通过.value
属性来获取实际的值。reactive
函数用于创建一个完整的响应式对象。它接收一个普通的JavaScript对象,并返回一个响应式的代理对象。你可以直接访问和修改响应式对象的属性,无需通过.value
来获取实际的值。
5-使用场景对比:
ref
适用于基本类型的数据,比如数字、字符串、布尔值等。它提供了简单的语法来访问和修改数据。reactive
适用于复杂的数据结构,比如对象和数组。它可以对整个对象或数组进行响应式处理,并提供了更细粒度的控制。
6-引用与值的关系
ref
函数创建的响应式引用是通过包装值来实现的,所以当你修改ref
的值时,会自动触发更新。而且,多个组件中对同一个ref
的引用会共享同一个引用,这意味着它们会同时更新。reactive
函数创建的响应式对象是通过代理对象来实现的,当你访问和修改响应式对象的属性时,会自动跟踪依赖,并在依赖发生改变时触发更新。每个组件都会有自己独立的响应式对象,它们之间不会相互影响。
3-计算属性和侦听属性
1-computed
- 计算属性(Computed Properties): 计算属性可以根据响应式数据的变化而动态计算出新的值。在Vue 3中,你可以使用
computed
函数来创建计算属性,并在组件中使用。
javascript
import { computed } from 'vue';
export default {
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
fullName() {
return this.firstName + ' ' + this.lastName;
}
}
}
在上面的例子中,我们使用computed
函数创建了一个名为fullName
的计算属性。计算属性的值是根据firstName
和lastName
的值计算而来的。当firstName
或lastName
的值发生变化时,fullName
会自动重新计算。
- 计算属性的优点:
计算属性是基于缓存来实现的,无论你后端调用十次还是几百次,只要计算属性依赖的相关值没有发生变化,那计算属性就可以通过缓存读取。例子如下:
xml
<template>
<!--下面是通过方法得出的名字-->
<div>{{userAllName()}}</div>
<div>{{userAllName()}}</div>
<!--下面是通过计算属性得出的名字-->
<div>{{userName}}</div>
<div>{{userName}}</div>
</template>
<script setup lang="ts">
import { reactive, computed } from "vue"
const allName = reactive({
userName1:'小', //姓
userName2:'明', //名
age:20,
})
const userName = computed(()=>{
console.log("我是计算属性调用的");
return allName.userName1 +
allName.userName2+"年龄"+allName.age
})
const userAllName = function(){
console.log("我是方法调用的");
return allName.userName1 + allName.userName2+"年龄"+allName.age
}
</script>
2-watch
侦听属性(Watch Properties):侦听属性可以用来观察和响应响应式数据的变化,并执行相应的操作。 默认是懒侦听的,即仅在侦听源发生变化时才执行回调函数。
第一个参数是侦听器的源。 第二个参数是在发生变化时要调用的回调函数。这个回调函数接受三个参数:新值、旧值,以及一个用于注册副作用清理的回调函数。
第三个可选的参数是一个对象,支持以下这些选项:
- immediate:在侦听器创建时立即触发回调。第一次调用时旧值是 undefined。
- deep:如果源是对象,强制深度遍历,以便在深层级变更时触发回调。
- flush:使侦听器在侦听器回调中能访问被 Vue 更新之后的DOM。
xml
<script setup lang="ts">
import { ref, watch } from "vue"
const count = ref(0)
/**
* 挑战 1: Watch 一次
* 确保副作用函数只执行一次
* 使用stopWatch停止侦听器
*/
const stopWatch=watch(count, () => {
console.log("Only triggered once")
stopWatch()
})
count.value = 1
setTimeout(() =>{ count.value = 2})
/**
* 挑战 2: Watch 对象
* 确保副作用函数被正确触发
* 使用deep深层次监听
*/
const state = ref({
count: 0,
})
watch(state, () => {
console.log("The state.count updated")
},{
deep:true,
})
state.value.count = 2
/**
* 挑战 3: 副作用函数刷新时机
* 确保正确访问到更新后的`eleRef`值
* 一般侦听器是在Vue组件更新之前被调用,所以要使用flush访问被Vue更新后的DOM
*/
const eleRef= ref()
const age = ref(2)
watch(age, () => {
console.log(eleRef.value)
},{ flush: 'post'})
age.value = 18
</script>
<template>
<div>
<p>
{{ count }}
</p>
<p ref="eleRef">
{{ age }}
</p>
</div>
</template>
补充:watch和watchEffect
相同点: 1、两者都可以监听data属性变化 2、watch 与 watchEffect 在手动停止侦听、清除副作用 (将 onInvalidate 作为第三个参数传递给回调)、刷新时机和调试方面有相同的行为。
区别 1、watch不加immediate初始值监听不到,watchEffect一开始就能监听到; 2、watch需要明确监听哪个属性; 3、watchEffect会根据其中的属性,自动监听其变化; 4、watcheffect初始化时,一定会执行一次(收集要监听的数据,不然不知道监听的是什么),watch只有你设置了初始化监听才会监听; 5、watchEffect获取不到更改前的值,而watch可以同时获取更改前和更改后的值;
3-生命周期函数
v3中组合式API中实现生命周期钩子函数可以在setup()函数中使用带有on前缀的函数: 因为 setup 是围绕 beforeCreate 和 created 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup 函数中编写。 这些函数接受一个回调函数,当钩子被组件调用时将会被执行: eg:
javascript
setup() {
// 组件被挂载时,我们用 onMounted 钩子记录一些消息
onMounted(() => console.log('component mounted!'));
}
4-自定义指令
4.1- v-model
v3中支持v-model传递多个参数;在Vue3
中,可以通过参数来达到一个组件支持多个v-model
的能力。v3中,v-model的使用方式也发生了一些变化,在v2中输入元素的双向绑定,但v3中,v-model更通用了,适用于任何可以通过value和input事件进行双向绑定的元素。 在v3中,可以使用v-model指令绑定一个变量到一个元素上,然后通过input事件来更新这个变量的值,举例
xml
<template>
<div>
<input v-model="message" />
<p>{{ message }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue 3'
}
}
}
</script>
上面的例子中,通过v-mode指令将message变量绑定到input元素上。当input元素值发生变化时,会自动更新message的值,同样,当message的值发生变化,也会自动更新input元素的值。
需要注意的是:v3中的v-model默认使用的是value属性和input事件,如果你想用其他属性和事件,可通过v-model后加上修饰符的方式进行配置。举例:如果你想用checked属性和change事件来绑定一个复选框的状态,可以这样写:
ini
<input type="checkbox" v-model:checked="isChecked" />
总结一下,在Vue 3中,v-model可以用于任何可以通过value和input事件进行双向绑定的元素,你可以通过修改修饰符来配置v-model使用的属性和事件。
5-新组件,新属性
1- v-bind(内置内容)
Vue3中的新增的v-bind()的常用使用方式,主要包括在css,less,scss中的使用
xml
<template>
<p>hello</p>
</template>
<style scoped>
/* 修改以下代码绑定动态颜色 */
p {
color: v-bind(theme);
line-height: v-bind('style.height');
border:solid;
width: v-bind(width+'px');
}
</style>
2-teleport 传送门
能将插槽内容渲染到 DOM 中的另一个指定位置。 在Vue 3中,teleport
是一种传送门机制,它可以将组件的内容渲染到DOM树中的指定位置,而不受组件层次的限制。这在处理模态框、弹出菜单等需要在DOM树中的其他位置渲染的情况下非常有用。
使用teleport
需要两个部分:一个发送端和一个接收端。
- 发送端: 在发送端组件中,你可以使用
<teleport>
标签将需要传送的内容包裹起来,并通过to
属性指定接收端的目标位置。
xml
<template>
<div>
<!-- 发送端组件内容 -->
<button @click="showModal">显示模态框</button>
<teleport to="#modal">
<!-- 需要传送的内容 -->
<Modal v-if="showModal" @close="closeModal" />
</teleport>
</div>
</template>
<script>
import Modal from './Modal.vue';
export default {
components: {
Modal
},
data() {
return {
showModal: false
}
},
methods: {
showModal() {
this.showModal = true;
},
closeModal() {
this.showModal = false;
}
}
}
</script>
在上面的例子中,我们通过<teleport>
标签将<Modal>
组件的内容传送到指定的位置,即带有id="modal"
的元素。 2. 接收端: 在接收端,你需要在指定位置设置一个容器,用于接收传送的内容。
xml
<template>
<div>
<!-- 接收端的容器 -->
<div id="modal"></div>
</div>
</template>
<script>
export default {
// ...
}
</script>
在上面的例子中,我们在接收端的模板中设置了一个带有id="modal"
的<div>
元素,作为传送内容的接收容器。
总结一下,teleport
是Vue 3中的一种传送门机制,可以将组件的内容渲染到DOM树中指定位置。通过在发送端使用<teleport>
标签将内容包裹起来,并通过to
属性指定接收位置,然后在接收端设置一个容器用于接收传送的内容。这样就可以实现组件的内容在DOM树中的非当前位置渲染的效果。
3、Suspense
允许应用程序在等待异步组件时渲染一些其它内容,让用户有一个更好体验。
使用步骤: 1、异步引入组件;
javascript
import {defineAsyncComponent} from 'vue'
const Child = defineAsyncComponent(()=>import('./components/Child.vue'))
2、使用Suspense包裹组件,并配置好default 与 fallback
(1) 插槽包裹异步组件;
(2) 插槽包裹渲染异步组件渲染之前的内容;
xml
<template>
<div class="app">
<h3>我是App组件</h3>
<Suspense>
<template v-slot:default>
<Child/>
</template>
<template v-slot:fallback>
<h3>加载中.....</h3>
</template>
</Suspense>
</div>
</template>
6-vue3的优点
1. 更好的性能:
- V3对编译器进行了重写,引入了新的编译器核心,提供了更快的编译速度和更小的包大小。
- 通过使用Proxy代理替代了Object.defineProperty,V3的响应式系统在性能上有了显著的提升。
2. 更小的包大小:
V3中通过优化编译和内部算法,减小了框架的包大小。同时,它还引入了Tree-shaking支持,可以更好地消除未使用的代码,进一步减小最终打包的体积。
- Composition API:
- V3引入了Composition API,它是一种基于函数的API风格,使得组件逻辑可以更好地封装和重用。
- Composition API提供了更灵活和强大的方式来组织和管理组件的逻辑,让代码更加清晰、可维护性更高。
3. 更好的TypeScript支持:
V3在内部使用TypeScript进行重写,并提供了更好的TypeScript支持,提供了更强的类型推断和类型检查。
1. Teleport:
- Vue 3引入了Teleport,这是一个传送门机制,可以将组件的内容渲染到DOM树中的指定位置,而不受组件层次的限制。
4. 更好的工具链:
V3对开发工具链进行了改进和优化,包括Vue Devtools和Vue CLI,使得开发者在开发和调试过程中更加高效。
总结一下:V3带来了更好的性能、更小的包大小、更灵活的Composition API、更好的TypeScript支持、Teleport传送门机制以及优化的开发工具链等优点。这些优点使得V3成为一个更强大、高效和开发友好的Web开发框架。