vue2和vue3的区别【持续更新】

3 篇文章 0 订阅
2 篇文章 0 订阅

目录

内部指令

组件之间通信

计算属性computed

watch

生命周期钩子

nextTick


vue有非常棒的官方文档,基本上看了就会用,其实没有再写博客的必要。因为最近在开发vue3的项目,所以初衷是为了系统性的归纳一下常常用到的内容,作为总结提炼的同时也和大家一起分享...

vue3官方文档:简介 | Vue.js

内部指令

vue2:

v-text更新元素的 textContent
v-html更新元素的 innerHTML
v-show根据表达式之真假值,切换元素的 display CSS property。
v-if根据表达式的值的 truthiness 来有条件地渲染元素。
v-else-if表示 v-if 的“else if 块”。可以链式调用。
v-else为 v-if 或者 v-else-if 添加“else 块”。
v-for基于源数据多次渲染元素或模板块。
v-on绑定事件监听器。缩写是  @。注意了解修饰符的使用。
v-bind动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。缩写是 : 。注意了解修饰符的使用。
v-model在表单控件或者组件上创建双向绑定。注意了解修饰符的使用。
v-slot提供具名插槽或需要接收 prop 的插槽。缩写是  #。
v-pre跳过这个元素和它的子元素的编译过程。
v-cloak这个指令保持在元素上直到关联实例结束编译。
v-once只渲染元素和组件一次

vue3:

v-memo3.2+。缓存一个模板的子树。在元素和组件上都可以使用。
v-bind修饰符:.prop和.attr调整。
v-on修饰符:不再支持使用数字 (即键码) 作为 v-on 修饰符,不再支持 .keyCodes

组件之间通信

vue2:

vm.$props父组件传值给子组件,子组件使用props进行接收。
vm.$emitvm.$emit( eventName, […args] )。触发当前实例上的事件。附加参数都会传给监听器回调。子组件传值给父组件。
vm.$parent、vm.$children和vm.$root组件中可以使用 $parent 和 $children 获取到父组件实例和子组件实例,进
而获取数据。
vm.$attrs和vm.$listeners可以通过 v-bind="$attrs" 和v-on="$listeners"传入内部组件。如:在对一些组件进行二次封装时可以方便传值。
vm.$refs一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例,直接获取数据。
 Vuex使用 Vuex 进行状态管理。
EventBusEventBus又称事件总线,相当于一个全局的仓库,任何组件都可以去这个仓库里获取事件。跨组件触发事件,进而传递数据。
provide / inject这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。
浏览器缓存例如 localStorage。

vue3:

Props

<script setup>
import { defineProps } from 'vue'
//一个组件需要显式声明它所接受的 props,这样 Vue 才能知道外部传入的哪些是 props,哪些是透传 attribute
const props = defineProps({
    tableData: {
        type: Array,
        default: () => {
            return []
        }
    },
})
//依然是所有的 props 都遵循着单向绑定原则,子组件不能修改父组件传过来的值。
props.tableData.push(...[2,3,4])
</script>

emit

<!-- 子组件 -->
<script setup>
import { defineEmits } from 'vue'
//显式声明emit,触发多个事件时以数组的形式声明
const emit = defineEmits(['emit1', 'emit2'])
const handleChange = (val) => {
    emit('emit1', val.emit1)
    emit('emit2', val.emit2)
}
</script>

<!-- 父组件 -->
<common-item @emit1="getEmit1" @emit2="getEmit2"></common-item>
<script setup>
const getEmit1 = (val) => {
    console.log('emit1',val)
};
const getEmit2 = (val) => {
    console.log('emit2',val)
};
</script>

# 注:官方文档说defineProps 和 defineEmits 都是只能在 <script setup> 中使用的编译器宏。他们不需要导入,且会随着 <script setup> 的处理过程一同被编译掉。但我在开发electron项目的时候不导入会报错,提示defineProps或defineEmits  is not defined.

$parent、$children和$root

vue3 setup里面没有this(官方:在 setup() 内部,this 不会是该活跃实例的引用,因为 setup() 是在解析其它组件选项之前被调用的,所以 setup() 内部的 this 的行为与其它选项中的 this 完全不同。这在和其它选项式 API 一起使用 setup() 时可能会导致混淆。),而且废除了$children。

$attrs和$listeners

1.vue2 中可以通过 this.$attrs 访问传递给组件的 attribute,以及通过 this.$listeners 访问传递给组件的事件监听器。

2.vue3 的虚拟 DOM 中,事件监听器现在只是以 on 为前缀的 attribute,这样事件监听器就成为了 $attrs 对象的一部分,因此 $listeners 被移除了。

$refs

Vuex

EventBus

EventBus 又称为事件总线。在Vue中可以使用 EventBus 来作为中间商,所有组件都可以访问,可以向该中心注册发送事件或接收事件,通过事件进行组件间通信,所有的组件都可以无阻碍地和其他组件通信。因为太方便,所以可能会造成难以维护的“灾难”,开发过程中往往需要慎重使用,一般不推荐,害怕导致问题需要系统性排查。因此有了更完善的Vuex作为状态管理中心,将通知的概念上升到共享状态层次。

vue2:

   初始化事件总线 EventBus 并将其导出,以便其它模块可以发送事件或者接收事件

初始化:

//方法一:
//创建一个 .js 文件,比如 eventBus.js
import Vue from 'vue'
export default new Vue()

//方法二:
//可以直接在项目中的 main.js 初始化 EventBus
// main.js
Vue.prototype.$EventBus = new Vue()

发送事件:

//引入事件总线
import EventBus from "@/utils/eventBus";
//发送事件“websocket”
EventBus.$emit("websocket", tipData);

接收事件:

//引入事件总线
import EventBus from "@/utils/eventBus";
//接收事件“websocket”
EventBus.$on("websocket", val => {
    if (val.typeDesc === "算法触发的消息") {
       this.getTableData();
    }
});

移除事件:

//引入事件总线
import EventBus from "@/utils/eventBus";
//移除事件“websocket”
EventBus.$off('websocket', {})

vue3:

正如所料,在vue3中$on, $once, $off实例方法已经被移除,组件实例不再实现事件触发接口,EventBus 已经成为了历史。vue3可以用发布订阅者模式实现的插件库(mitt)也可以自己模拟。
这个方式其实有点像 Vuex 或者 Pinia 那样,创建一个 Bus.js 文件,用来控制数据和注册事件。

Bus.js

import { ref } from 'vue'

class Bus {
  constructor() {
    // 收集订阅信息,调度中心
	this.eventList = {}, // 事件列表,这项是必须的
    // 下面的都是自定义值
	this.msg = ref('这是一条总线的信息')
  }

  // 订阅
  $on(name, fn) {
	this.eventList[name] = this.eventList[name] || []
	this.eventList[name].push(fn)
  }

  // 发布
  $emit(name, data) {
	if (this.eventList[name]) {
      this.eventList[name].forEach((fn) => {
        fn(data)
      });
	}
  }

  // 取消订阅
  $off(name) {
      if (this.eventList[name]) {
	  delete this.eventList[name]
	}
  }
}

export default new Bus()

用法:

组件A:

<script setup>
import Bus from '../Bus.js'

//发布
let exitClick = () => {
  Bus.$emit('exit', false)
}
</script>

组件B:

<script setup>
import Bus from './Bus.js'

// 订阅
Bus.$on('exit', data => {
  isShowPage.value = data
})
</script>

localStorage

这个兄弟不归vue管,没有什么你的我的,用起来也比较简单,存取操作。

Window.localStorage - Web API 接口参考 | MDN只读的localStorage 属性允许你访问一个Document 源(origin)的对象 Storage;存储的数据将保存在浏览器会话中。localStorage 类似 sessionStorage,但其区别在于:存储在 localStorage 的数据可以长期保留;而当页面会话结束——也就是说,当页面被关闭时,存储在 sessionStorage 的数据会被清除 。https://developer.mozilla.org/zh-CN/docs/Web/API/Window/localStorage

计算属性computed

<!--   vue2   -->
// html
<div>{{ total(3) }}</div>
<div v-if="isShow">测试元素</div>
// js
computed: {
    total() {
        return function (n) {
            return n * this.num
        }
    },
    isShow: function() {
        return this.role === 'admin' && this.age > '18'
    }
}

<!--   vue3   -->
// html
<div>{{ total(3) }}</div>
<div v-if="isShow">测试元素</div>
// js
<script setup>
import { computed } from 'vue'
const total = computed(() => (n) => {
    return n * this.num
})
const isShow = computed(() => {
    return this.role === 'admin' && this.age > '18'
})
</script>

watch

<!--   vue2   -->
watch: {
    formData: {
        handler(newForm, oldForm) {
            console.log(newForm)
        },
        immediate: true,
        deep: true
    }
}

<!--   vue3   -->
<script setup>
import { watch } from 'vue'
watch(
    () => formData,
    (newForm, oldForm) => {
        console.log(newForm)
    },
    { immediate: true, deep: true }
)
</script>

生命周期钩子

我们可以使用生命周期钩子在组件各个生命阶段添加逻辑,如常见的onMounted

vue2图示:Vue 实例 — Vue.jsVue.js - The Progressive JavaScript Frameworkhttps://v2.cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA

vue3图示:生命周期钩子 | Vue.jsVue.js - 渐进式的 JavaScript 框架https://cn.vuejs.org/guide/essentials/lifecycle.html

生命周期钩子:

组合式 API:生命周期钩子 | Vue.jsVue.js - 渐进式的 JavaScript 框架https://cn.vuejs.org/api/composition-api-lifecycle.html

  • beforeCreate -> 使用 setup()
  • created -> 使用 setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy-> onBeforeUnmount
  • destroyed-> onUnmounted

nextTick

<!--   vue2   -->
data(){
    return {
        visible: false
    }
}
// 直接使用
this.$nextTick(() => {
    // 执行操作
    this.visible = true
    this.getData()
})

<!--   vue3   -->
<template>
    <div class="main-content">
        <p v-if="visible">hello</p>
    </div>
</template>
<script setup>
import { ref, nextTick } from 'vue'
const visible = ref(false)
// 使用
nextTick(() => {
    // 执行操作
    visible.value = true
    this.getData()
})
</script>

官方:
const count = ref(0)
async function increment() {
  count.value++
  // DOM 还未更新
  console.log(document.getElementById('counter').textContent) // 0
  await nextTick()
  // DOM 此时已经更新
  console.log(document.getElementById('counter').textContent) // 1
}
结语:才学疏浅,有写错或者漏写的地方 还望指正,一起持续更新,不断打磨, 感谢🤞~
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值