1.Templatefragments碎片
组件可以拥有多个根节点,解决多个div嵌套问题
2.数据获取
Vue3的数据获取在反应数据(Reactive Data)中,通常包含在一个反应状态(Reactive State)变量中。(reactive的作用是将对象包装成响应式对象,通过Proxy代理后的对象。)
响应式原理: Proxy代理拦截:reactive函数执行,会将传入的target对象通过Proxy包装,拦截它的get,set等,并将代理的target缓存。(组件在render阶段,视图会读取数据对象上的值进行渲染,此时便触发了Proxy的get,由此触发对应的track函数,记录下了对应的ReactiveEffect,也就是常说的依赖收集。)
1).Ref与reactive区别:
reactive 和 ref 都是用来定义响应式数据的, reactive更推荐去定义复杂的数据类型, ref 更推荐定义基本类型,ref 和 reactive 本质我们可以简单的理解为ref是对reactive的二次包装, ref定义的数据访问的时候要多一个.value。(ref定义基本数据类型,ref也可以定义数组和对象)
2).判断数据到底是ref还是reactive?
通过isRef / isReactive 方法,对当前数据的__v_ref来判断的,如果有这个私有的属性, 并且取值为true, 那么就代表是一个ref类型的数据
3.响应式数据
在Vue3.0,我们就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
使用以下三步来建立反应性数据:
1)从vue引入reactive
2)使用reactive()方法来声名我们的数据为反应性数据
【前端|简述 vue3.0与2.0区别】3)使用setup()方法来返回我们的反应性数据,从而template可以获取这些反应性数据
import { reactive } from 'vue'
export default {
props: {
title: String
},
setup () {
const state = reactive({
username: '',
password: ''
})return { state }
}}
这里构造的反应性数据就可以被template使用,可以通过state.username和state.password获得数据的值,需要先声名一个方法然后在setup()方法中返回(return), 在组件内就可以调用这个方法了。
4.methods方法
Vue3 的合成型API里面的setup()方法也是可以用来操控methods的。创建声名方法其实和声名数据状态是一样的。需要先声名一个方法然后在setup()方法中返回(return), 这样组件内就可以调用这个方法了。
export default {
props: {
title: String
},
setup () {
const state = reactive({
username: '',
password: ''
})const login = () => {
// 登陆方法}
return {
login,
state
}
}}
5.生命周期钩子
现在 Vue3 的合成型API里面的setup()方法可以包含了基本所有东西。生命周期的钩子就是其中之一!但是在 Vue3 生周期钩子不是全局可调用的了,需要另外从vue中引入,生命周期的挂载钩子叫onMounted,引入后我们就可以在setup()方法里面使用onMounted挂载的钩子了。(与2.0生命周期相似,在前面加了on,setup这个生命周期发生在beforeCreate和created之前,此时无法访问data、computed、methods、refs )
6.计算属性 - Computed Properties
Vue3 的设计模式给予开发者们按需引入需要使用的依赖包,在 Vue3 使用计算属性,需要在组件内引入computed。使用方式就和反应性数据(reactive data)一样,在state中加入一个计算属性。(计算属性可以写在声明的响应式变量内,也可单独声明使用)
setup () {
const state = reactive({
username: '',
password: '',
lowerCaseUsername: computed(() => state.username.toLowerCase())
}) const twiceTheCounter = computed(() => counter.value * 2)
7.接收 Props
接收组件props参数传递这一块为我们带来了Vue2和Vue3之间最大的区别。在 Vue2,this代表的是当前组件,不是某一个特定的属性。所以我们可以直接使用this访问prop属性值。就比如下面的例子在挂载完成后打印处当前传入组件的参数title。在 Vue3 中,this无法直接拿到props属性,emit events(触发事件)和组件内的其他属性。不过全新的setup()方法可以接收两个参数:1.props - 不可变的组件参数
2.context - Vue3 暴露出来的属性(emit,slots,attrs)
setup (props,context) {
//Context的使用(// attrs (非响应式对象,等同于 $attrs用于简介传参,slots插槽 非响应式对象,等同于 $slots,emit触发事件方法,等同于 $emit,expose 暴露公共property 函数,将setup里的内容暴露到外部)
onMounted(() => {
console.log('title: ' + props.title)
})一个项目使用
//父组件里的子组件
//子组件的内容
{{title}}
8.模板引用
为了获得对模板内元素或组件实例的引用,一样声明 ref 并从 setup() 返回:
This is a root element
这里在渲染上下文中暴露root,并通过ref=”root”,将其绑定到div作为其ref。(在虚拟dom补丁算法中,若Vnode的ref键对应于渲染上下文中的 ref,则 VNode 的相应元素或组件实例将被分配给该 ref 的值。这是在虚拟 DOM 挂载/打补丁过程中执行的,因此模板引用只会在初始渲染之后获得赋值,即在onMounted生命周期中)
9.watch监听
使用从 Vue 导入的 watch 函数执行相同的操作。它接受 3 个参数:
- 一个想要侦听的响应式引用或 getter 函数
- 一个回调
- 可选的配置选项
import {watch } from 'vue'
//一个变量
const counter = ref(0)
//监听函数 watch(监听的值,回调,可选的配置选项)
watch(counter, (newValue, oldValue) => {
console.log('The new counter value is: ' + counter.value)
})
注意:侦听模板引用的变更可以替代前面例子中演示使用的生命周期钩子。
但与生命周期钩子的一个关键区别是watch() 和 watchEffect()在 DOM 挂载或更新之前运行副作用,所以当侦听器运行时,模板引用还未被更新。因此,使用模板引用的侦听器应该用 flush: 'post' 选项来定义,这将在 DOM 更新后运行,确保模板引用与 DOM 保持同步。
watchEffect(() => {
console.log(root.value) // => This is a root element
},
{
flush: 'post'
})
10.Mixin
简述:Mixin 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个 mixin 对象可以包含任意组件选项。当组件使用 mixin 对象时,所有 mixin 对象的选项将被“混合”进入该组件本身的选项。
局部mixins的配置:
export const mixin1 = {
methods: {
showName(){
alert('第一个mixin')
}
},
mounted() {
console.log('你好啊!')
},}
export const mixin2 = {
data() {
return {
sum:100
}
},
methods: {
showName(){
alert('第二个mixin')
}
},
}
全局注册:全局mixins 对vm,和所有vm均进行mixins
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
import {mixin1,mixin2} from '../mixin'
//关闭Vue的生产提示
Vue.config.productionTip = false
Vue.mixin(mixin1)
Vue.mixin(mixin2)
//创建vm
new Vue({
el:'#app',
render: h => h(App)
})
11.自定义组件
除了核心功能默认内置的指令 (例如 v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。
举个聚焦输入框的例子,如下:
//全局注册
const app = Vue.createApp({})// 注册一个全局自定义指令 `v-focus`
app.directive('focus', {
// 当被绑定的元素挂载到 DOM 中时……
mounted(el) {
// 聚焦元素
el.focus()
}})
注册局部指令:
directives: {
focus: {
// 指令的定义
mounted(el) {
el.focus()
}
}}注册局部指令:
directives: {
focus: {
// 指令的定义
mounted(el) {
el.focus()
}
}}
使用方式:
使用方式
12. 路由变化
传参和原来一样,取参发生改变:
Params传参:
点击跳转到home页面并传参
vue3.0中import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.params.id);
//111
query传参:
test
//接受的时候
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query.id);
//999
Js传参方式:
import { useRouter } from 'vue-router'
const route = useRouter()
route.push({
path:"/lianxi",
query:{
id:666
}
});
route.push({
name:'lianxi',
params:{
id:666
}
});
import { useRoute } from 'vue-router'
const route = useRoute()
console.log(route.query.id);
//999
13.总结
现在基本都看到vue2与vue3其实概念与理念都是一样的。只是有一些属性获取方式和声名和定义方式稍微变了。总结一下,我觉得 Vue3 给我们前端开发者带来了全新的开发体验,更好的使用弹性,可控度也得到了大大的提升。全新的合成式API(Composition API)可以提升代码的解耦程度 —— 特别是大型的前端应用,效果会更加明显。还有就是按需引用的有了更细微的可控性,让项目的性能和打包大小有更好的控制。
案例项目代码整理:
{{ state.title }}
Values: {{ state.username + ' ' + state.password }}
推荐阅读
- vue3.0|【vue3.0】vue2.0到vue3.0的变化(区别)(上)
- vue3.0|vue2.0到vue3.0有这一篇就够了
- 前端|VUE3.0和VUE2.0语法上的不同
- vue|vue3.0新特性及与vue2.0的区别
- 《重构 JavaScript》读后感和部分摘录
- #yyds干货盘点#java接收前端map报错不能被转换
- vue|vue个人在线简历
- vue3|While resolving: aidr-web-service-web@1.0.0 vue3安装依赖报错
- vue|vue3组件封装之搜索组件的封装