vue2和vue3的区别

vue2和vue3的区别

前言:很多小伙伴在面试的时候会遇到面试官会问vue框架的版本更替,以及vue2向vue3推进时是一个巨大的改变,会问到vue2和vue3的区别,以下是我个人整理的一些主要的区别,如有不对还希望各位大佬指出,我这边及时更正。

1.响应式对比

1.1 vue2中使用Object.defineProperty

// Vue 2 - 响应式系统(Object.defineProperty)
new Vue({
  el: '#app',
  data() {
    return {
        state:{
    	  message: 'Hello Vue 2'
        }
    };
  },
  computed: {
    reversedMessage() {
      return this.message.split('').reverse().join('');
    }
  }
});

1.2 vue3中使用Proxy

// Vue 3 - 响应式系统(Proxy)
const { createApp, reactive, computed } = Vue;

const app = createApp({
  setup() {
    const state = reactive({
      message: 'Hello Vue 3'
    });

    const reversedMessage = computed(() => state.message.split('').reverse().join(''));

    return { state, reversedMessage };
  }
});

app.mount('#app');

1.3 vue2不能监听到对象中的属性的新增、删除需要用到this. s e t 。 v u e 3 中删除 set。vue3中删除 setvue3中删除set,属性删除和新增和响应式

在 Vue2中,如果你直接给一个对象新增或删除属性,Vue 的响应式系统无法检测到这种变动。这是因为 JavaScript 对象的属性在新增或删除时,Vue 2 的响应式系统无法自动劫持这些操作。为了解决这个问题,Vue 2 提供了 this.$set 方法,来保证新增属性是响应式的。
// Vue 2
this.$set(this.state, 'newProperty', 'value');
由于 Vue3使用 Proxy 进行响应式处理,直接修改对象的属性(包括新增)会自动触发视图更新,而且是响应式的。
state.newProperty=value

2. API差异

2.1 vue2使用 Options API

// Vue 2 Options API 示例
new Vue({
  el: '#app',
  data() {
    return {
      count: 0
    };
  },
  computed: {
    doubledCount() {
      return this.count * 2;
    }
  },
  methods: {
    increment() {
      this.count++;
    }
  }
});

2.2 Vue 3 使用 Composition API

写法1:
// Vue 3 Composition API 示例
const { createApp, ref, computed } = Vue;

const app = createApp({
  setup() {
    // 定义响应式变量
    const count = ref(0);

    // 定义计算属性
    const doubledCount = computed(() => count.value * 2);

    // 定义方法
    const increment = () => {
      count.value++;
    };

    return {
      count,
      doubledCount,
      increment
    };
  }
});

app.mount('#app');

3.v-model 用法

3.1 Vue 2 中v-model默认是绑定 value 属性

<!-- Vue 2 v-model 示例 -->
<template>
  <div>
    <input v-model="message" />
    <p>{{ message }}</p>
  </div>
</template>

<script>
new Vue({
  el: '#app',
  data() {
    return {
      message: 'Hello Vue 2'
    };
  }
});
</script>

3.2 Vue 3中v-model支持多个绑定属性和事件自定义

<!-- Vue 3 多个 v-model 示例 -->
<template>
  <child-component v-model:title="title" v-model:content="content" />
</template>

<script>
const { defineComponent, ref } = Vue;

const ChildComponent = defineComponent({
  props: {
    title: String,
    content: String
  },
  emits: ['update:title', 'update:content'],
  template: `
    <div>
      <input :value="title" @input="$emit('update:title', $event)" />
      <textarea :value="content" @input="$emit('update:content', $event)"></textarea>
    </div>
  `
});

const app = createApp({
  components: { ChildComponent },
  setup() {
    const title = ref('Title');
    const content = ref('Content');
    return { title, content };
  }
});

app.mount('#app');
</script>

4.Fragments(多个根元素)

4.1 Vue 2 每个组件必须有一个根元素

<!-- Vue 2 组件必须有一个根元素 -->
<template>
  <div>
    <p>Message: {{ message }}</p>
  </div>
</template>

<script>
new Vue({
  el: '#app',
  data() {
    return {
      message: 'Hello Vue 2'
    };
  }
});
</script>

4.2 Vue 3 支持多个根元素(Fragments)

<!-- Vue 3 组件可以有多个根元素 -->
<template>
  <p>Message: {{ message }}</p>
  <button @click="increment">Increment</button>
</template>

<script>
const { createApp, ref } = Vue;

const app = createApp({
  setup() {
    const message = ref('Hello Vue 3');
    const increment = () => {
      message.value += '!';
    };
    return { message, increment };
  }
});

app.mount('#app');
</script>

5.生命周期

5.1 vue2生命周期

beforeCreate:实例刚被创建,数据和事件还未初始化。
created:实例创建完成,数据已响应,事件/Watcher 已设置。
beforeMount:在挂载开始之前调用,el 和 template 还没有被渲染。
mounted:挂载完成,DOM 已经渲染,适合做网络请求或操作 DOM。
beforeUpdate:数据变化导致重新渲染之前调用。
updated:组件更新并重新渲染后调用。
beforeDestroy:组件销毁前调用,可以在此做清理操作(如移除事件监听)。
destroyed:组件销毁后调用。

new Vue({
  el: '#app',
  data() {
    return {
      message: 'Hello Vue 2'
    };
  },
  created() {
    console.log('created');
  },
  mounted() {
    console.log('mounted');
  },
  beforeUpdate() {
    console.log('beforeUpdate');
  },
  updated() {
    console.log('updated');
  },
  beforeDestroy() {
    console.log('beforeDestroy');
  },
  destroyed() {
    console.log('destroyed');
  },
  methods: {
    someMethod() {
      console.log('Some method');
    }
  }
});

5.2 vue3生命周期

setup:实例创建完成,数据已响应,事件/Watcher 已设置。
onBeforeMount:在挂载开始之前调用,el 和 template 还没有被渲染。
onMounted:挂载完成,DOM 已经渲染,适合做网络请求或操作 DOM。
onBeforeUpdate:数据变化导致重新渲染之前调用。
onUpdated:组件更新并重新渲染后调用。
onBeforeUnmount:组件销毁前调用,可以在此做清理操作(如移除事件监听)。
onUnmounted:组件销毁后调用。


import { createApp, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue';

const app = createApp({
  setup() {
    // 生命周期钩子在 setup 中调用
    onBeforeMount(() => {
      console.log('beforeMount');
    });
    
    onMounted(() => {
      console.log('mounted');
    });

    onBeforeUpdate(() => {
      console.log('beforeUpdate');
    });

    onUpdated(() => {
      console.log('updated');
    });

    onBeforeUnmount(() => {
      console.log('beforeUnmount');
    });

    onUnmounted(() => {
      console.log('unmounted');
    });
  }
});

app.mount('#app');

6.组件传值

6.1 vue2

父传子

<!-- 父组件 -->
<template>
  <div>
    <Child :message="parentMessage" />
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child,
  },
  data() {
    return {
      parentMessage: 'Hello from parent',
    };
  },
};
</script>


<!-- 子组件 -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  props: {
    message: String,
  },
};
</script>

子向父

<!-- 父 -->
<template>
  <div>
    <Child @sendMessage="receiveMessage" />
  </div>
</template>

<script>
import Child from './Child.vue';

export default {
  components: {
    Child,
  },
  methods: {
    receiveMessage(message) {
      console.log('Received from child:', message);
    },
  },
};
</script>

<!-- 子 -->
<template>
  <button @click="sendMessage">Send Message to Parent</button>
</template>

<script>
export default {
  methods: {
    sendMessage() {
      this.$emit('sendMessage', 'Hello from child');
    },
  },
};
</script>

6.2 vue3

父传子

<!-- 父组件 -->
<template>
  <div>
    <Child :message="parentMessage" />
  </div>
</template>

<script setup>
import Child from './Child.vue';
import { ref } 'vue';
let parentMessage = ref("parentMessage")
</script>


<!-- 子组件 -->
<template>
  <div>
    <p>{{ props.message }}</p>
  </div>
</template>

<script setup>
import { ref } 'vue';    
const props = defineProps({
      message: {
        type: String,
        required: true,
      },
    });
</script>

子传父

<!-- 父 -->
<template>
  <div>
    <Child @customEvent="customEvent" />
  </div>
</template>

<script>
import Child from './Child.vue';
const customEvent =(e)=>{
	console.log('Received from child:', e);
}
</script>

<!-- 子 -->
<template>
  <button @click="sendMessage">Send Message to Parent</button>
</template>

<script setup>
// 使用 defineEmits() 来声明事件
const emit = defineEmits();

// 触发事件
const sendMessage = () => {
	emit('customEvent', 'Hello from Child');
};
</script>

7.v-if和v-for的优先级

7.1 vue2

在vue2中v-for的优先级高于v-if,可以放在一起使用,但是不建议这么做,会带来性能上的浪费

7.2 vue3

在vue3中v-if的优先级高于v-for,一起使用会报错。可以通过在外部添加一个标签,将v-for移到外层

8.diff算法不同

8.1 vue2

遍历每一个虚拟节点,进行虚拟节点对比,并返回一个patch对象,用来存储两个节点不同的地方。用patch记录的消息去更新dom
缺点:比较每一个节点,而对于一些不参与更新的元素,进行比较是有点消耗性能的。特点:特别要提一下Vue的patch是即时的,并不是打包所有修改最后一起操作DOM,也就是在vue中边记录变更新。(React则是将更新放入队列后集中处理)。

8.3 vue3

在初始化的时候会给每一个虚拟节点添加一个patchFlags,是一种优化的标识。只会比较patchFlags发生变化的节点,进行识图更新。而对于patchFlags没有变化的元素作静态标记,在渲染的时候直接复用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值