1. vue2和vue3双向数据绑定原理发生了改变
vue2 的双向数据绑定是利用ES5 的一个 API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。
vue3 中使用了 es6 的 ProxyAPI 对数据代理。
相比于vue2.x,使用proxy的优势如下
defineProperty只能监听某个属性,不能对全对象监听
可以省去for in、闭包等内容来提升效率(直接绑定整个对象即可)
可以监听数组,不用再去单独的对数组做特异性操作 vue3.x可以检测到数组内部数据的变化
2. Vue3支持碎片(Fragments)
就是说在组件可以拥有多个根节点。

3. Composition API

vue2
-
-
export default {
-
props: {
-
title: String
-
},
-
data () {
-
return {
-
username: '',
-
password: ''
-
}
-
},
-
methods: {
-
login () {
-
// 登陆方法
-
}
-
},
-
components:{
-
"buttonComponent":btnComponent
-
},
-
computed:{
-
fullName(){
-
return this.firstName+" "+this.lastName;
-
}
-
}
-
-
}
-
vue3
-
export default {
-
props: {
-
title: String
-
},
-
-
setup () {
-
const state = reactive({ //数据
-
username: '',
-
password: '',
-
lowerCaseUsername: computed(() => state.username.toLowerCase()) //计算属性
-
})
-
//方法
-
const login = () => {
-
// 登陆方法
-
}
-
return {
-
login,
-
state
-
}
-
}
-
}
4. 建立数据 data
Vue2 - 这里把数据放入data属性中
-
-
export default {
-
props: {
-
title: String
-
},
-
data () {
-
return {
-
username: '',
-
password: ''
-
}
-
}
-
}
-
在Vue3.0,我们就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
使用以下三步来建立反应性数据:
从vue引入reactive
使用reactive()方法来声名我们的数据为响应性数据
使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据

5. 生命周期钩子


总结:
1、setup 函数时,它将接受两个参数:(props、context(包含attrs、slots、emit))
2、setup函数是处于 生命周期函数 beforeCreate 和 Created 两个钩子函数之前的函数
3、执行 setup 时,组件实例尚未被创建(在 setup() 内部,this 不会是该活跃实例的引用,即不指向vue实例,Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)
4、与模板一起使用:需要返回一个对象 (在setup函数中定义的变量和方法最后都是需要 return 出去的 不然无法再模板中使用)
5、使用渲染函数:可以返回一个渲染函数,该函数可以直接使用在同一作用域中声明的响应式状态
注意事项:
1、setup函数中不能使用this。Vue 为了避免我们错误的使用,直接将 setup函数中的this修改成了 undefined)
2、setup 函数中的 props 是响应式的,当传入新的 prop 时,它将被更新。但是,因为 props 是响应式的,你不能使用 ES6 解构,因为它会消除 prop 的响应性。
如果需要解构 prop,可以通过使用 setup 函数中的toRefs 来完成此操作:
父传子,props
-
import { toRefs } from 'vue'
-
-
setup(props) {
-
const { title } = toRefs(props)
-
-
console.log(title.value)
-
onMounted(() => {
-
console.log('title: ' + props.title)
-
})
-
-
}
子传父,事件 - Emitting Events



7. vue3 Teleport瞬移组件
Teleport一般被翻译成瞬间移动组件,实际上是不好理解的.我把他理解成"独立组件",
他可以那你写的组件挂载到任何你想挂载的DOM上,所以是很自由很独立的
以一个例子来看:编写一个弹窗组件
-
<template>
-
<teleport to="#modal">
-
<div id="center" v-if="isOpen">
-
<h2><slot>this is a modal</slot></h2>
-
<button @click="buttonClick">Close</button>
-
</div>
-
</teleport>
-
</template>
-
<script lang="ts">
-
-
export default {
-
props: {
-
isOpen: Boolean,
-
},
-
emits: {
-
'close-modal': null
-
},
-
setup(props, context) {
-
const buttonClick = () => {
-
context.emit('close-modal')
-
}
-
return {
-
buttonClick
-
}
-
}
-
}
-
</script>
-
<style>
-
#center {
-
width: 200px;
-
height: 200px;
-
border: 2px solid black;
-
background: white;
-
position: fixed;
-
left: 50%;
-
top: 50%;
-
margin-left: -100px;
-
margin-top: -100px;
-
}
-
</style>
-
在app.vue中使用的时候跟普通组件调用是一样的
-
<template>
-
<div id="app">
-
<img alt="Vue logo" src="./assets/logo.png">
-
<HelloWorld msg="Welcome to Your Vue.js App"/>
-
<HooksDemo></HooksDemo>
-
<button @click="openModal">Open Modal</button><br/>
-
<modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal>
-
</div>
-
-
</template>
-
<script>
-
import HelloWorld from './components/HelloWorld.vue'
-
import HooksDemo from './components/HooksDemo.vue'
-
import Modal from './components/Modal.vue'
-
import{ref} from 'vue'
-
export default {
-
name: 'App',
-
components: {
-
HelloWorld,
-
HooksDemo,
-
Modal
-
},
-
setup() {
-
const modalIsOpen = ref(false)
-
const openModal = () => {
-
modalIsOpen.value = true
-
}
-
const onModalClose = () => {
-
modalIsOpen.value = false
-
}
-
return {
-
modalIsOpen,
-
openModal,
-
onModalClose
-
}
-
}
-
}
-
</script>
-
-
<style>
-
#app {
-
font-family: Avenir, Helvetica, Arial, sans-serif;
-
-webkit-font-smoothing: antialiased;
-
-moz-osx-font-smoothing: grayscale;
-
text-align: center;
-
color: #2c3e50;
-
margin-top: 60px;
-
}
-
</style>
-
-
要是在app.vue文件中使用的时候,modal是在app的 DOM节点之下的,父节点的dom结构和css都会给modal产生影响
于是产生的问题
modal被包裹在其它组件之中,容易被干扰
样式也在其它组件中,容易变得非常混乱
Teleport 可以把modal组件渲染到任意你想渲染的外部Dom上,不必嵌套在#app中,这样就可以互不干扰了,可以把Teleport看成一个传送门,把你的组件传送到任何地方
使用的时候 to属性可以确定想要挂载的DOM节点下面
-
<template>
-
<teleport to="#modal">
-
<div id="center">
-
<h2>柏特better</h2>
-
</div>
-
</teleport>
-
</template>
-
在public文件夹下的index.html中增加一个节点
-
<!DOCTYPE html>
-
<html lang="en">
-
<head>
-
<meta charset="utf-8">
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
-
<meta name="viewport" content="width=device-width,initial-scale=1.0">
-
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
-
<title><%= htmlWebpackPlugin.options.title %></title>
-
</head>
-
<body>
-
<noscript>
-
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
-
</noscript>
-
<div id="app"></div>
-
<div id="modal"></div>
-
<!-- built files will be auto injected -->
-
</body>
-
</html>
-
转载:https://blog.csdn.net/m0_62877814/article/details/128935510