Vue3.0和2.0语法不同分析

前言:本篇文章只做VUE3.0和VUE2.0语法上的不同分析,不做性能和源码架构等的分析。

一、VUE3.0和VUE2.0代码结构不同

VUE3.0代码实例

<template>
  <div>
    <span>count is {{ count }}</span>
    <span>plusOne is {{ plusOne }}</span>
    <button @click="increment">count++</button>
  </div>
</template>
 
<script>
import { value, computed, watch, onMounted, ref } from 'vue'
 
export default {
  setup() {
    // ref state
    const count = ref(0)
    // computed state
    const plusOne = computed(() => count.value + 1)
    // method
    const increment = () => { count.value++ }
    // watch
    watch(() => count.value * 2, val => {
      console.log(`count * 2 is ${val}`)
    })
    // lifecycle
    onMounted(() => {
      console.log(`mounted`)
    })
    // expose bindings on render context
    return {
      count,
      plusOne,
      increment
    }
  }
}
</script>

也可以不用写setup函数,可以直接把setup写到script标签上
VUE3.0代码实例

<template>
  <div>
    <span>count is {{ count }}</span>
    <span>plusOne is {{ plusOne }}</span>
    <button @click="increment">count++</button>
  </div>
</template>

<script setup lang="ts">
import { computed, watch, onMounted, ref } from 'vue'

// ref state
const count = ref(0)
// computed state
const plusOne = computed(() => count.value + 1)
// method
const increment = () => { count.value++ }
// watch
watch(() => count.value * 2, val => {
  console.log(`count * 2 is ${val}`)
})
// lifecycle
onMounted(() => {
  console.log(`mounted`)
})

</script>

相应的VUE2.0代码实例

<template>
    <div>
        <span>count is {{ count }}</span>
        <span>plusOne is {{ plusOne }}</span>
        <button @click="increment">count++</button>
    </div>
</template>
 
<script>
    export default {
        data() {
            return {
                count: 0
            };
        },
        methods: {
            increment: function () {
                this.count++;
            }
        },
        computed: {
            plusOne: function () {
                return this.count + 1;
            }
        },
        watch: {
            count: function (val) {
                console.log(`count * 2 is ${val * 2}`)
            }
        },
        mounted() {
            console.log(`mounted`);
        }
    };
</script>

VUE2.0和VUE3.0的代码对比一下:VUE2.0是将mounted、data、computed、watch之类的方法作为VUE对象的属性进行导出。VUE3.0新增了一个名为setup的入口函数,value, computed, watch, onMounted等方法都需要从外部import
在这里插入图片描述

二、关于VUE3.0和VUE2.0生命周期

VUE2.0生命周期

1、beforeCreate:在实例初始化之后、进行数据侦听和事件/侦听器的配置之前同步调用
2、created:在实例创建完成后被立即同步调用。在这一步中,实例已完成对选项的处理,意味着以下内容已被配置完毕:数据侦听、计算属性、方法、事件/侦听器的回调函数。然而,挂载阶段还没开始,且 $el property 目前尚不可用。
3、beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。
4、mounted:在实例挂载完成后被调用。
5、beforeUpdate:在数据发生改变后,DOM 被更新之前被调用。这里适合在现有 DOM 将要被更新之前访问它,比如移除手动添加的事件监听器。
6、updated:在数据更改导致的虚拟 DOM 重新渲染和更新完毕之后被调用。
7、activated:被 keep-alive 缓存的组件激活时调用。
8、deactivated:被 keep-alive 缓存的组件失活时调用。
9、beforeUnmount:在卸载组件实例之前调用。在这个阶段,实例仍然是完全正常的。
10、unmounted:卸载组件实例后调用。调用此钩子时,组件实例的所有指令都被解除绑定,所有事件侦听器都被移除,所有子组件实例被卸载。
在这里插入图片描述

VUE3.0生命周期

1、setup: 同VUE2.0的beforeCreate和created。
2、onBeforeMount:同VUE2.0的beforeMount。
3、onMounted:同VUE2.0的mounted。
4、onBeforeUpdate:同VUE2.0的beforeMount。
5、onUpdated:同VUE2.0的updated。
6、onBeforeUnmount:同VUE2.0的beforeUnmount。
7、onUnmounted:同VUE2.0的unmounted。
8、onMounted:同VUE2.0的beforeMount。
9、onActivated:同VUE2.0的activated。
10、onDeactivated:同VUE2.0的deactivated。

三、VUE3.0和VUE2.0响应式

VUE3.0响应数据
1、ref():让简单类型的数据变成响应式数据。这种数据是Number或者String等基本类型数据,这种数据是通过值而非引用传递的类型。

import { ref } from 'vue'

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

2、reactive(): 让复杂类型数据变成响应式,不需要.value包裹。

import { reactive } from 'vue'

// 响应式状态
const state = reactive({
  count: 0
})

state.count.value++
console.log(state.count) // 1

注意:当ref作为响应式对象的值被更改时,ref的内部值也会发生改变。

const count = ref(0)
const state = reactive({
  count
})

console.log(state.count) // 0

state.count = 1
console.log(count.value) // 1

注意:使用ES6解构响应式对象时,响应式会丢失。

import { reactive } from 'vue'

const book = reactive({
  author: 'Vue Team',
  year: '2020',
  title: 'Vue 3 Guide',
  description: 'You are reading this book right now ;)',
  price: 'free'
})

let { author, title } = book

对于这种情况,我们需要将我们的响应式对象转换为一组 ref。这些 ref 将保留与源对象的响应式关联,使用toRefs():

import { reactive, toRefs } from 'vue'

const book = reactive({
  author: 'Vue Team',
  year: '2020',
  title: 'Vue 3 Guide',
  description: 'You are reading this book right now ;)',
  price: 'free'
})

let { author, title } = toRefs(book)

title.value = 'Vue 3 Detailed Guide' // 我们需要使用 .value 作为标题,现在是 ref
console.log(book.title) // 'Vue 3 Detailed Guide'

在使用 ts 时如何申明对象


import { reactive } from 'vue';
 
interface Person {
  name: string;
  age: number;
  gender: string;
  [key: string | number]: string |number | boolean;  // 动态添加属性
}
// 任意动态添加属性
interface DynamicObject {
  [key: string]: any;
}
const person: Person = reactive({
  name: "Tom",
  age: 18,
  gender: "male"
});

通过 ref 函数定义响应式包装器:

import { ref } from 'vue';
 
interface Person {
  name: string;
  age: number;
  gender: string;
}
 
const person = ref<Person>({
  name: "Tom",
  age: 18,
  gender: "male"
});

watch监听属性
VUE3.0 watch监听

import { ref, watch } from 'vue'

const counter = ref(0)
watch(counter, (newValue, oldValue) => {
  console.log('The new counter value is: ' + counter.value)
})

VUE2.0 watch监听

export default {
  data() {
    return {
      counter: 0
    }
  },
  watch: {
    counter(newValue, oldValue) {
      console.log('The new counter value is: ' + this.counter)
    }
  }
}

computed计算属性
VUE3.0 computed计算

import { ref, computed } from 'vue'

const counter = ref(0)
const twiceTheCounter = computed(() => counter.value * 2)

counter.value++
console.log(counter.value) // 1
console.log(twiceTheCounter.value) // 2

VUE2.0 computed计算

Vue.createApp({
  data() {
    return {
      counter: 0
    }
  },
  computed: {
    twiceTheCounter() {
      return counter * 2
    }
  }
}).mount('#demo')

父子组件通过props传递值
VUE3.0 props

// MyBook.vue
export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}

或者

<script setup>
const props = defineProps({
  title: {
    type: String
  }
})
</script>

第二种方式是比较常见的,那获取props中的数值呢
template直接取值

<template>
    <div class="test">
        <button v-if="!show">show</button>
    </div>
</template>
 
<script lang="ts" setup>
import { defineProps } from 'vue'
 
let props = defineProps({
    show: Boolean
});
</script>
<script lang="ts" setup>
import { toRefs} from 'vue'
 
let props = defineProps({
    show: Boolean,
    data: Object,
    number: Number
});
// toRefs 解构赋值
let { show, data, number } = toRefs(props);
const show = props.show;
const data= props.data;
</script>

这样做可以直接使用data和show,无需props.show,但有一个致命的缺陷,数据会失去响应式,所以解构时,需要用torefs包裹,因为props本质上时reactive对象,torefs可以把reactive的每个属性变成ref对象,这样解构出来依旧是响应式。(torefs使用需要引入,defineprops不需要)

VUE2.0 props

export default {
  name: 'Demo',
  props: {
    count: {
      type: Number,
      default: 1
    },
   arrValue: {
      type: Array,
      default () {
        return []
      }
    }
  },
  mounted() {
    console.log(this.count)
  }
 }

emit子组件向父组件抛出事件

VUE2.0
VUE2.0可以通过this.$emit()向父组件抛出事件

VUE3.0

setup(props, { emit }) {
    const close = ()=>{
        emit("change")    
    }
    return{
        close
    }
}

或者

<script setup>
const emit = defineEmits(["change"])

const close = ()=>{
        emit("change")    
    }
</script>

$refs

VUE2.0
vue2.0可以直接通过this.$refs.访问子组件

VUE3.0

<template>
  <div ref="refDemo" />
</template>
<script setup>
const refDemo = ref()
console.log(refDemo.value)
</script>

注意:1、通过变量的命名要和ref相同。 2、通过ref来访问子组件的方法,子组件要通过expose将事件和变量暴露出来,这样父组件才能访问到
import { defineExpose } from ‘vue’;
defineExpose({ childFun });

VUE3.0 context
VUE2.0
VUE2.0可以通过this来访问VUE实例上的方法和变量。例如this.emit、this.refs、this.$slots

VUE3.0
context 是一个普通 JavaScript 对象,暴露了其它可能在 setup 中有用的值:

export default {
  setup(props, context) {
    // Attribute (非响应式对象,等同于 $attrs)
    console.log(context.attrs)

    // 插槽 (非响应式对象,等同于 $slots)
    console.log(context.slots)

    // 触发事件 (方法,等同于 $emit)
    console.log(context.emit)

    // 暴露公共 property (函数)
    console.log(context.expose)
  }
}

注意:在setup时,你只能访问props、attrs、slots、emit。无法访问data、computed、methods、refs (模板 ref)

VUE3.0 获取当前路由地址

import { useRouter } from "vue-router"
const router = useRouter()
console.log('路由', router.currentRoute)

更多内容可以看官方文案官方地址

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: Vue 3.0和2.0之间存在一些区别。首先,在初始化方面,Vue 3.0可以在安装脚手架时提前安装一些项目开发必备的插件,并且提供了可视化创建脚手架的功能,使得插件和依赖的管理和配置更加方便。此外,两个版本的目录结构也有一些差别。\[1\] 其次,在模板语法方面,Vue 3.0引入了Composition API,这是一种新的API风格,可以更灵活地组织和复用组件逻辑。在模板中,Vue 3.0使用<template>标签来包裹组件的内容,而在Vue 2.0中,使用<template>标签来包裹组件的内容。\[2\]\[3\] 总结来说,Vue 3.0相对于2.0在初始化和目录结构上有一些改进,同时引入了Composition API来提供更灵活的组件逻辑组织方式。 #### 引用[.reference_title] - *1* [vue2.0和3.0的区别(面试必备~)](https://blog.csdn.net/weixin_47208955/article/details/112336471)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [【经典面试题】vue2与vue3的区别](https://blog.csdn.net/m0_64346035/article/details/124855972)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值