1. 数据双向绑定的原理
1.1 原理
- Vue2.0使用
Object.defineProperty
来劫持对象属性的 geter 和 seter 操作,当数据改变发出通知 - Vue3.0使用
ES6的新特性porxy
来劫持数据,当数据改变时发出通知
1.2 由于原理造成的差异
// vue2.0 data
export default {
data() {
return {
obj: {a: 1},
arr: []
};
}
};
// vue3.0 data
export default defineComponent({
setup() {
const currData = reactive({
obj: {a: 1},
arr: []
});
return {
...toRefs(currData)
};
},
});
版本 | Vue2.0 | Vue3.0 |
---|---|---|
object新增属性 | 1. Vue.set() : this.$set(this.obj, b, 2);2. Object.assign() : Object.assign(this.obj, {b:2}); |
直接赋值 :currData. obj.b = 2 |
array新增属性 |
push : this.arr.push(1); |
直接下标 : currData. arr[0] = 1; |
2. 生命周期
2.0 周期名称 | 3.0 周期名称 | 说明 |
---|---|---|
beforeCreate | setup | 组件创建之前 |
created | setup | 组件创建完成 |
beforeMount | onBeforeMount | 组件挂载之前 |
mounted | onMounted | 组件挂载完成 |
beforeUpdate | onBeforeUpdate | 数据更新,虚拟 DOM 打补丁之前 |
updated | onUpdated | 数据更新,虚拟 DOM 渲染完成 |
beforeDestroy | onBeforeUnmount | 组件销毁之前 |
destroyed | onUnmounted | 组件销毁后 |
/**
* vue2.0 生命周期
* 配置化的
**/
export default {
beforeCreate() {},
created() {}
};
/**
* vue3.0 生命周期
* 都放在setup中
* 需要从vue引用
**/
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted,
ref
} from 'vue'
export default defineComponent({
setup() {
onBeforeMount (() => {});
onMounted (() => {});
}
});
3. 子组件使用emit方式与父组件通信
- 父组件代码(vue2.0 & vue3.0写法一致)
<!-- 父组件中调用子组件 -->
<child-comp @selfClick="selfClick" />
- 子组件代码
<button @click="clickBtn"></button>
/**
* vue2.0
* 配置化的methods
**/
export default {
methods: {
clickBtn() {
this.$emit('selfClick', '参数等');
}
}
};
/**
* vue3.0
* setup中直接使用自定义方法
**/
export default defineComponent({
setup(props, context) {
const clickBtn = () => {
context.emit('selfClick', '参数等');
};
return {
clickBtn
};
}
});
4. computed的使用
/**
* vue2.0
* 配置化的computed
**/
export default {
computed: {
uploadTitle() {
return this.filesList.length >= 5 ? '每条跟进备注至多添加5个附件' : '上传附件,最多5个';
}
},=
};
/**
* vue3.0
* setup中直接使用computed
**/
// 需要从 vue 中导出引入
import { computed } from 'vue'
export default defineComponent({
setup(props, context) {
const bigCount = computed(() => {
return count.value * 10;
})
return {
count,
bigCount
};
}
});
5. watch的使用
/**
* vue2.0
* 配置化的watch
**/
export default {
watch: {
options: {
immediate: true,
handler(list) {
if (Array.isArray(list)) {
list.forEach(i => i.component = 1);
}
}
}
},
};
/**
* vue3.0
**/
// 监听一个响应式数据
import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newValue, oldValue) => {
});
// 监听多个响应式数据
import { ref, watch } from 'vue'
const count = ref(0)
const count2 = ref(1)
watch([count, count2], ([newCount, newCount2], [oldCount, oldCount2]) => {
})
//还有第二种写法
watch([count, count2], (newValue, oldVlaue) => {
console.log(newValue)//[newCount, newCount2]
console.log(oldValue)//[oldCount, oldCount2]
})
6. framents
在 Vue3.x 中,组件现在支持有多个根节点
<!-- Layout.vue -->
<template>
<header>...</header>
<main v-bind="$attrs">...</main>
<footer>...</footer>
</template>
7. Teleport
- Teleport 是一种能够将我们的模板移动到 DOM 中 Vue app 之外的其他位置的技术,就有点像哆啦A梦的“任意门”
- 在vue2.X中,像 modals,toast 等这样的元素,如果我们嵌套在 Vue 的某个组件内部,那么处理嵌套组件的定位、z-index 和样式就会变得很困难
- 通过Teleport,我们可以在组件的逻辑位置写模板代码,然后在 Vue 应用范围之外渲染它
<button @click="showToast" class="btn">打开 toast</button>
<!-- to 属性就是目标位置 -->
<teleport to="#teleport-target">
<div v-if="visible" class="toast-wrap">
<div class="toast-msg">我是一个 Toast 文案</div>
</div>
</teleport>
其他:
- 过滤filter 被废弃
- ref的含义不同
- <template> 没有特殊指令的标记 (v-if/else-if/else、v-for 或 v-slot) 现在被视为普通元素,并将生成原生的 <template> 元素,而不是渲染其内部内容。
- 插槽的写法不同
- eventBus不再支持(可参考https://juejin.cn/post/6890781300648017934)
-
off 和 $once 实例方法被移除
参考文献:
https://github.com/febobo/web-interview/issues/33
https://juejin.cn/post/6890781300648017934
https://blog.csdn.net/qq_41328247/article/details/115937136
网友评论