VUE2和VUE3区别对比一览
## Vue3总结
### 官方文档
* [Vue3](https://v3.cn.vuejs.org/api/options*data.html)
* [Vue2](https://vuejs.bootcss.com/api/)
### Vue3相对于Vue2的语法特性
#### 1.获取数据
* vue2
```javascript
export default {
data() {
return {
name: 'myName',
}
},
mounted() {
console.log(this.name)
}
}
- vue3
import {ref} from 'vue'
export default {
setup() {
const name = ref('myName')
console.log(name.value)
return {name}
}
}
2.使用方法
- vue2
export default {
methods: {
show() {
console.log('show方法被调用')
}
},
mounted() {
this.show()
}
}
- vue3
import {onMounted} from 'vue'
export default {
setup() {
function show() {
console.log('show方法被调用')
}
onMounted(() => {
show()
})
return {show}
}
}
3.子组件向父组件通信
- vue2
export default {
methods: {
change() {
this.$emit('valueChange', 3)
}
},
}
- vue3
import {onMounted} from 'vue'
export default {
setup(props, context) {
function change() {
context.emit('valueChange', 3)
}
}
}
4.获取Vuex对象
- vue2
export default {
mounted() {
console.log(this.$store.state.name)
this.$store.commit('show')
}
}
- vue3
import {onMounted} from 'vue'
import {useStore} from 'vuex'
export default {
setup(props, context) {
const store = useStore()
onMounted(() => {
console.log(store.name)
store.commit('show')
})
}
}
5.v-for里的ref
- vue3
<template>
// el当前元素,divs是存储每个元素的数组
<div v-for="(item, index) in list" :ref="el => { divs[index] = el }">{{ item }}</div>
</template>
<script>
import {onMounted, ref} from 'vue';
export default {
setup() {
const divs = ref([]);
onMounted(() => {
console.log(divs.value)
});
return {
divs
};
},
};
</script>
6.Vue3支持碎片,就是说在组件可以拥有多个根节点
- vue2
<template>
<div class='form-element'>
<h2>{{ title }}</h2>
</div>
</template>
- vue3
<template>
<div class='form-element'></div>
<h2> {{ title }}</h2>
</template>
7.Composition API
- Vue2与Vue3 最大的区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)
- 旧的选项型API在代码里分割了不同的属性: data,computed属性,methods,等等。新的合成型API能让我们用方法(function)来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。
- 建立数据 data - Vue2中会把数据放入data属性中,Vue3中需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发
- 从vue引入reactive
- 使用reactive()方法来声名我们的数据为响应性数据
- 使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据
- vue2
export default {
props: {
title: String
},
data () {
return {
username: '',
password: ''
}
},
methods: {
login () {
// 登陆方法
}
},
components:{
"buttonComponent":btnComponent
},
computed:{
lowerCaseUsername(){
return this.username.toLowerCase();
}
}
}
- vue3
<template>
<div>
<h2> {{ state.username }} </h2>
</div>
</template>
<script>
import { reactive } from 'vue'
export default {
props: {
title: String
},
setup () {
const state = reactive({ //数据
username: '',
password: '',
lowerCaseUsername: computed(() => state.username.toLowerCase()) //计算属性
})
//方法
const login = () => {
// 登陆方法
}
return {
login,
state
}
}
}
</script>
8.生命周期钩子 — Lifecyle Hooks
Vue2--------------vue3
beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
activated -> onActivated
deactivated -> onDeactivated
9.父子组件传参
import { toRefs } from 'vue'
setup(props, { attrs, slots, emit }) {
const { title } = toRefs(props)
console.log(title.value)
onMounted(() => {
console.log('title: ' + props.title)
})
}
10.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>
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">
<button @click="openModal">Open Modal</button><br/>
<modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal>
</div>
</template>
<script>
import Modal from './components/Modal.vue'
import{ref} from 'vue'
export default {
name: 'App',
components: {
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>
- Teleport 可以把modal组件渲染到任意你想渲染的外部Dom上,不必嵌套在#app中,这样就可以互不干扰了,可以把Teleport看成一个传送门,把你的组件传送到任何地方
- 使用的时候 to属性可以确定想要挂载的DOM节点下面
- 在public文件夹下的index.html中增加一个节点,这样可以看到modal组件就是没有挂载在app下,不再受app组件的影响了
<body>
<div id="app"></div>
<div id="modal"></div>
</body>
11.vue2与vue3在标签或者组件中的ref="formRef"的dom元素的使用
- vue2中直接使用this. r e f s . f o r m R e f 或者 t h i s . refs.formRef或者this. refs.formRef或者this.refs[‘formRef’]的方式就可以获取该组件或者dom的内容
- vue3中由于setup函数中没有了this,那该如何使用呢?
<template>
<div ref="mainContainer" ></div>
</template>
<script>
setup() {
const mainContainer = ref(null)
onMounted(()=>{console.log(mainContainer)})
return {
mainContainer,
}
}
</script>
- 由于setup函数创建时还没有VNode 所以想要使用该属性必须得在onMounted函数里面可以使用获取
###table—cloums中render函数渲染组件的写法:
import { resolveComponent } from 'vue' // 需先引入 resolveComponent
cloums中写法render写法
{
title: '操作',
align: 'center',
width: 100,
fixed: 'right',
key: 'couTypeCategoryName',
render: (h, params) => {
return h(resolveComponent('el-switch'), {
modelValue: params.row.isShow,
'active-value': 1,
'inactive-value': 0,
// 'onUpdate:modelValue': value => params.row.state = value
onChange: (val) => {
},
})
}
},
一、在Table表格中渲染input、switch等 在 3.x v-model中,自定义组件相当于传递一个modelValue prop 并发出一个update:modelValue事件
render: (h, params) => {
return h(resolveComponent('el-input'), {
size: 'small',
modelValue: params.row.comments,
'onUpdate:modelValue': (value) => (params.row.comments = value),
})
},
二、插槽
<template #footer>
<span class="dialog-footer">
<el-button>取消</el-button>
<el-button type="primary">确定</el-button>
</span>
</template>
三、filters
在vue3中被移除
###Fragment
vue2每个模版必须有一个根节点
vue3可以有多个根节点
<!--vue2-->
<template>
<div>
<span></span>
<span></span>
</div>
</template>
<!--vue3-->
<template>
<span>hello</span>
<span>world</span>
</template>
###v-if v-for 优先级
vue2 时 v-for 优先级高,所以v-for 和v-if一起会耗性能,增加了喝多不必要的判断
vue3 v-if比v-for有更高的优先级
###vVNode Prop
vue2和vue3的虚拟dom参数有所区别,vue3更加扁平化
<!--vue2-->
render: (h, params) => {
let btnArr = [
h(
'Button',
{
props: {
type: 'primary',
},
style: {
marginLeft: '8px',
},
on: {
click: () => {
this.modalType = 'detail'
this.viewType = 2
this.item = params.row
this.pageStatus = true
this.pState = true
},
},
},
'查看详情'
),
]
return h('div', btnArr)
},
<!--vue3-->
render:(h,params)=>{
return h(resolveComponent('el-input-number'), {
type: 'number',
size: 'large',
modelValue:params.row.value,
stepStrictly:true,
controls:false,
min:"1",
'onUpdate:modelValue':(value) => { params.row.value = parseInt(value)},
style: { width:'200px'},
})
}
###ref和reactive 响应式的基础
接受一个参数,返回一个响应式数据
不同的是ref一般处理基础数据类型,reactive一般处理引用数据类型
使用 reactive,toRefs 保证 reactive 对象属性保持响应性
import { ref, computed, reactive, toRefs } from 'vue'
setup() {
const DataProps = reactive({
count: 0,
increase: () => { data.count++},
double: computed(() => data.count * 2)
})
const refData = toRefs(data)
return {
...refData
}
}
###v-model
vue2只能绑定一个,vue3可以绑定多个
<!--父组件-->
<template>
// v-model:modelValue简写为v-model
// 可绑定多个v-model
<child
v-model="state.name"
v-model:age="state.age"
/>
</template>
<script setup>
import { reactive } from 'vue'
// 引入子组件
import child from './child.vue'
const state = reactive({
name: 'Jerry',
age: 20
})
</script>
子组件
<template>
<span @click="changeInfo">我叫{{ modelValue }},今年{{ age }}岁</span>
</template>
<script setup>
// import { defineEmits, defineProps } from 'vue'
// defineEmits和defineProps在<script setup>中自动可用,无需导入
// 需在.eslintrc.js文件中【globals】下配置【defineEmits: true】、【defineProps: true】
defineProps({
modelValue: String,
age: Number
})
const emit = defineEmits(['update:modelValue', 'update:age'])
const changeInfo = () => {
// 触发父组件值更新
emit('update:modelValue', 'Tom')
emit('update:age', 30)
}
</script>
###defineComponent函数,只是对setup函数进行封装,返回options的对象;
###父组件获取子组件的属性和方法
<!--父组件-->
<template>
<child ref="comp"></child>
<button @click="handlerClick">按钮</button>
</template>
<script setup>
import child from "./comp/expose.vue"
import { ref } from "vue"
const comp = ref(null)
const handlerClick = () => {
console.log(comp.value.a) // 获取子组件对外暴露的属性
comp.value.someMethod() // 调用子组件对外暴露的方法
}
</script>
<!--子组件-->
<template>
<div>{{a}}</div>
<button @click='someMethod'>按钮子</button>
</template>
<script setup>
import { ref } from 'vue'
let someMethod=()=>{
console.log(666)
}
const a = 1
const b = ref(2)
defineExpose({
a,
b,
someMethod
})
</script>
###其他
1.vue2 defineProperty只能监听某个属性,不能对全对象监听
2 vue3 Proxy 代理,可以检测到数组内部数据的变化
3.vue3 Teleport瞬移组件
4.Vue2 - 这里把数据放入data属性中
5.vue 3 Composition API
需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
从vue引入reactive
使用reactive()方法来声名我们的数据为响应性数据
使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据
vue3Composition API生命后期
setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
onBeforeMount() : 组件挂载到节点上之前执行的函数。
onMounted() : 组件挂载完成后执行的函数。
onBeforeUpdate(): 组件更新之前执行的函数。
onUpdated(): 组件更新完成之后执行的函数。
onBeforeUnmount(): 组件卸载之前执行的函数。
onUnmounted(): 组件卸载完成后执行的函数