Vue2与Vue3 setup的使用差异与对比

news2025/2/2 3:43:12

最近一直在做vue2的技术栈升级,于是心血来潮,就想要不写篇文章总结一下vue2和vue3在使用上的不同吧,于是乎,我们这就开始吧!

在这里插入图片描述

首先说明一下,vue3有多种写法,本文使用setup语法糖,不考虑defineComponent的情况。

主要内容

1.slot 的用法

vue2

<el-tooltip placement="top">
  <!-- vue2 slot使用方式是任意标签设置属性【slot="slot名称"】 -->
  <div slot="content">自定义content信息</div>
  <el-button>Top center</el-button>
</el-tooltip>

vue3

<Tooltip placement="top">
  <!-- vue3 slot使用方式是template标签设置属性【#slot名称】 -->
  <template #content>
    <span>自定义content信息</span>
  </template>
  <Button>Top center</Button>
</Tooltip>

2.props 的用法

vue2

// vue2 使用option api风格,在props内定义父组件传入的props
export default {
	props: {
	    title: {
	      type: String,
	      default: '这是标题'
	    }
  },
}

vue3

<script setup lang="ts">
import { withDefaults, defineProps } from 'vue';

// vue3 使用defineProps定义父组件传入的props,同时可使用withDefaults定义属性默认值
const props = withDefaults(defineProps<{
  title: string;
}>(), {
  title: '这是标题'
});
</script>

3.data 数据的定义和修改

vue2

export default {
	data () {
		return {
			title: '新增'formData: {
				username: '',
				password: ''
			}
		}
	},
	methods: {
		changeTitle () {
			this.title = '编辑'
		},
		changeFormData () {
			this.$set(formData, 'username', '章三')
			this.$set(formData, 'password', '000000')
		}
	}
}

vue3

import { ref, reactive } from 'vue';

const title = ref<string>('新增');
const formData = reactive({
	username: '',
	password: ''
})
const changeTitle = () => {
	title.value = '编辑'
}
const changeFormData = () => {
	formData.username = '章三'
	formData.password = '000000'
}

4.emit 事件定义

vue2

export default {
	methods: {
		submit () {
			const data = {}
			this.$emit('change', data)
		}
	}
}

vue3

import { defineEmits } from 'vue';

const emit = defineEmits(['change'])
const submit = () => {
	const data = {}
	emit('change', data)
}

5.computed 的使用

vue2

export default {
  computed: {
    userNames (userList) {
      return userList.map(user => user.name)
    }
  }
}

vue3

import { computed, ref } from 'vue';

const userList = ref<User[]>([])
const userNames = computed(() => userList.value.map(user => user.name))
// 下面为需要传值的情况
const userNames = computed(() => (userListParams: User[]) => {
  return userListParams.map(user => user.name)
});

6.watch 的使用

vue2

export default {
  watch: {
    userList: {
      handler: function (val) {
        // todo	
      },
      deep: true,
      immediate: true
    }
  },
}

vue3

import { watch, ref } from 'vue';

const userList = ref<User[]>([])

watch(
// 这里也可以直接写userList.value
  () => userList.value,
  () => {
    // todo
  },
  {
  	deep: true,
    immediate: true
  }
);

7. 父组件调用子组件内的方法

vue2
不需要额外的设置,直接通过this.$refs调用即可

父组件

<List ref="listRef" />
export default {
  mounted () {
	this.$refs.listRef?.getList()
  }
}

vue3
需要子组件通过 defineExpose方法先暴露出来父级需要用到的方法

父组件

<List ref="listRef" />
import { ref, onMounted } from 'vue';

const listRef = ref()

onMounted(() => {
	listRef.value?.getList()
})

子组件

import { defineExpose } from 'vue';

const getList = () => {
	// TODO
}

defineExpose({
	getList
})

8. router路由参数获取与路由跳转

vue2
直接使用this.$router调用录音方法, 使用 this.$route获取路由参数

export default {
  mounted () {
  	const params = this.$route.query
	this.$router.push({
		path: '/page/list',
		query: {
			name: 'dxxxxx'
		}
	})
  }
}

vue3
需要引入 useRouteruseRoute并执行hooks后使用

import { onMounted } from 'vue';
import { useRouter, useRoute } from 'vue-router';

const router = useRouter();
const route = useRoute();

onMounted(() => {
	const params = route.query
	router.push({
		path: '/page/list',
		query: {
			name: 'dxxxxx'
		}
	})
})

9. provide与inject

vue2
父组件

export default {
   provide () {
    return {
      deleteFn: (id) => {
        // TODO
      },
      userName: '张三'
    }
  },
}

子组件使用

export default {
   inject: ['userName', 'deleteFn'],
}

vue3
父组件

import { provide, ref } from 'vue';

const deleteFn = (id: string) => {
  // TODO
}
const userName = ref<string>('张三')

provide('deleteFn', deleteFn);
provide('userName', userName);

子组件使用

import { inject, ref } from 'vue';

const deleteFn = inject('deleteFn');
const userName = inject('userName');

10. 生命周期函数

vue2 八个

beforeCreate created beforeMount mounted
beforeUpdate updated beforeDestroy destroyed

vue3 六个

onBeforeMount onMounted onBeforeUpdate onUpdated onBeforeUnmount onUnmounted

说明:vue2中的beforeCreate和created对应的其实是vue3的setup

11. 页面路由拦截

如果使用的是vue3 setup语法糖来写组件,而有需要使用页面路由拦截来做一些事情的时候,处理起来会比较麻烦,需要结合vue3 defineComponent的写法来实现。当然,也可以直接整个页面都使用defineComponent而不是setup语法糖

vue2

export default {
   beforeRouteEnter (to, from, next) {
    // TODO
    next()
  },
}

vue3
需要注意的是,项目中可能因为重复引入vue和多个script标签而导致eslint报错,这时需要禁用掉当前行的eslint检查。

<script setup lang="ts">

import {
  ref, onMounted,
  // 这里是为了解决eslint报错问题
  // eslint-disable-next-line import/no-duplicates
} from 'vue';

...
</script>

<script lang="ts">
// 这里是为了解决eslint报错问题
// eslint-disable-next-line import/first, import/no-duplicates
import { defineComponent } from 'vue';

export default defineComponent({
  beforeRouteEnter(to, from, next) {
    // TODO
    next();
  },
});
</script>

12. 动态循环component组件如何设置ref来使用子组件中的方法?

vue2

<component
  v-for="item in componentList"
  :is="item.name"
  :ref="`${item.name}-ref`"
  :key="item.name"
></component>
import PageA from './components/page-a.vue'
import PageB from './components/page-b.vue'

export default {
	data () {
		return {
			componentList: [
		        {
		          label: '页面A',
		          // value对应组件名
		          name: 'page-a'
		        },
		        {
		          label: '页面B',
		          name: 'page-b'
		        },
	      	],
	      	currentPage: 'page-a'
		}
	},
	mounted () {
		// 获取ref
		this.$refs[`${currentPage}-ref`]?.getData()
	}
}

vue2
vue3无法使用name直接用于component,需要传入真实的组件

<component
	v-for="item in componentList"
    :is="item.component"
    :ref="(el) => setTabRef(el, item.name)"
    :key="item.name"
></component>
import { ref, reactive, onMounted } from 'vue';

import PageA from './components/page-a.vue'
import PageB from './components/page-b.vue'


const componentList = ref([
  {
    label: '页面A',
    // value对应组件名
    name: 'pageA',
    // 这里需要传入真实的组件
    component: PageA
  },
  {
    label: '页面B',
    name: 'pageB',
    // 这里需要传入真实的组件
    component: PageB
  }
])

// 存储动态子组件的ref
const tabRefs = reactive<any>({});
const currentPage = ref('pageA')

const setTabRef = (el: any, key: string) => {
  tabRefs[key] = el;
};

onMounted(() => {
	// 获取ref
	tabRefs[currentPage]?.getData()
})

想法(仅个人)

  1. vue2升级vue3的时间成本和技术代价有点高了,感觉这也是vue的一个缺点吧
  2. vue3开放了多种写法,虽然选择比较自由,但不同写法又有不同的缺点,感觉这也是vue做的不够好的地方。比如defineComponent需要最后返回所有的数据和方法,不然template无法使用;比如setup语法糖下,无法使用路由拦截…
  3. 砥砺前行,vue的道路还很长~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104198.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

硬核!Github 星标 79.4K 的阿里强推 Java 面试参考指南到底有多强?

谈到 Java 面试&#xff0c;相信大家第一时间脑子里想到的词肯定是金三银四&#xff0c;金九银十。好像大家的潜意识里做 Java 开发的都得在这个时候才能出去面试&#xff0c;跳槽成功率才高&#xff01;但 LZ 不这么认为&#xff0c;LZ 觉得我们做技术的一生中会遇到很多大大小…

组件技术--设计--jsp+servlet+bean+MySQL 简单的登录注册案例

JavaBeanMySQLjspservlet 简单的登录注册案例登录注册案例需求核心系统组成Javaweb项目框架基本思想BeancounterUserDaoUserDaoservletLoginCljspindex.jspLoginServlet.jspregister.jspregisterMessage.jspwelcome.jsptargetpom.xmlWEB-INFweb.xml登录注册案例需求 本项目利用…

【论文阅读笔记】CycleISP: Real Image Restoration via Improved Data Synthesis

论文地址&#xff1a;https://arxiv.org/abs/2003.07761 代码地址&#xff1a;https://github.com/swz30/CycleISP 论文小结 总的来说&#xff0c;就是现实世界中无法获取有效的图像对。且之前合成噪声的方式是在sRGB上添加高斯白噪声&#xff0c;但对于相机传感器成像管道来说…

工控CTF之协议分析7——OMRON

协议分析 流量分析 主要以工控流量和恶意流量为主&#xff0c;难度较低的题目主要考察Wireshark使用和找规律&#xff0c;难度较高的题目主要考察协议定义和特征 简单只能简单得干篇一律&#xff0c;难可以难得五花八门 常见的工控协议有&#xff1a;Modbus、MMS、IEC60870、…

同源策略跨域

目录1.同源策略限制的意义1.请求协议 均为 http2.主机此这为 localhost3.端口号不同 一个 8080 一个 50002.注意3.解决跨域代理服务器 80801.同源策略限制的意义 让前端发送的请求不能随意访问其他端口的服务器&#xff0c;一定程度保护服务器和用户的隐私 1.请求协议 均为 …

nexus上传jar包

nexus上传自定义starter1、普通jar包和springboot的starter1.1、starter上传简介1.2、上传方法2.1.1、setting.xml文件2.1.2、项目中的pom文件1.3、具体部署2、父pom文件上传这里我们主要讲解两种&#xff0c;一种是jar包上传&#xff0c;包含普通jar包和springboot的starter包…

jmeter简单压力测试

测试目的&#xff1a;10个用户并发访问一个接口&#xff08;http://127.0.0.1:8080/dfm/login.action&#xff09;&#xff0c;能否正常响应。 一、打开JMeter 二、右击“测试计划”&#xff0c;添加线程组 三、设置线程组的线程数 JMeter中的线程组&#xff0c;类似于LoadRunn…

RCTFweb复现

文章目录filechecker_minieasy_uploadfilechecker_plusfilechecker_pro_maxezbypassezruoyifilechecker_mini 给了附件&#xff0c;代码比较短&#xff0c;先审计一下。 在这里发现了file –b命令&#xff0c;且filepath部分可控&#xff0c;明显的ssti漏洞&#xff0c;没过…

Clickhouse引擎之kafka

Clickhouse kafka引擎需要结合kafka使用&#xff0c;需要确保已经安装clickhouse和kafka 实战环境&#xff1a; Clickhouse-server 版本&#xff1a;22.4.5 Kafka版本&#xff1a;kafka_2.13-3.2.0 Clickhouse数据库执行&#xff1a; 1、使用引擎创建一个kafka消费者 CREA…

【OpenCV+Qt】使用车牌识别系统EasyPR识别车牌号

EasyPR是一个中文的开源车牌识别系统&#xff0c;其车牌识别划分为了两个过程&#xff1a;即车牌检测&#xff08;Plate Detection&#xff09;和字符识别&#xff08;Chars Recognition&#xff09;两个过程&#xff1a; 车牌检测&#xff08;Plate Detection&#xff09;&am…

用于医疗诊断的花青染料ICG-Sulfo-EG8-OSu,

凯新生物产品介绍&#xff1a; (ICG)是一个用于医疗诊断的花青染料。它是用于测定心输出量、肝脏功能、肝血流量,和对于眼科血管造影术。它有一个最大吸收光谱在800nm附近。这些红外波段可以穿透视网膜层,相比荧光素血管造影ICG血管造影图像允许进入更深的血液循环。传统的激活…

华为机试_HJ24 合唱队【中等】【收藏】

目录 描述 输入描述&#xff1a; 输出描述&#xff1a; 解题过程 提交代码 学习代码 代码一 代码二 收藏点 描述 N 位同学站成一排&#xff0c;音乐老师要请最少的同学出列&#xff0c;使得剩下的 K 位同学排成合唱队形。 设KK位同学从左到右依次编号为 1&#xff0…

想学Redis却不会安装,这有一个快速入门请拿去

一. Redis简介 1.什么是Redis Redis是一个完全开源免费、且遵守BSD协议的&#xff0c;高性能(NOSQL)的key-value数据库。Redis本身使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型&#xff0c;并提供多种语言的API。 2.Redis特点 Redis具有如下特点&#xff1…

DJ13-2 汇编语言程序设计

目录 一、顺序程序设计 二、分支程序设计 1. 用比较/测试命令条件转移指令实现分支 2. 采用跳转表实现多路分支 三、循环程序设计 1. 计数循环程序设计 2. 条件判断循环程序设计 四、子程序设计 1. 子程序设计举例 2. 主程序和子程序设计举例 一、顺序程序设计 举例…

低代码为什么会受到企业青睐?是何原因?

低代码为什么会受到企业青睐&#xff1f;是何原因&#xff1f;回答这个问题&#xff0c;只需用4个“更”字&#xff0c;就能很好的概括。 1、更快&#xff08;开箱即用&#xff09; 2、更省&#xff08;人力、时间成本&#xff09; 3、更合适&#xff08;需求贴合业务&#…

mfc常用控件

mfc在编写桌面客户端应用应用程序&#xff0c;在设计界面时&#xff0c;如果像一般的界面&#xff0c;实施人员或者适配人员使用(特定的用户群体)对界面要求没有那么高&#xff0c;只要软件功能正常&#xff0c;稳定就行&#xff0c;我们在做这些界面时&#xff0c;通常使用原生…

CSDN第16期竞赛

目录 1.比赛详情 2.竞赛感悟 3.竞赛题目回顾 &#xff08;1&#xff09;鬼画符门莲台争夺战 (2)津津的储蓄计划 &#xff08;3&#xff09;多边形的面积 (4)小桥流水人家 1.比赛详情 比赛地址&#xff1a;http://t.csdn.cn/b1Lzm 2.竞赛感悟 通过这次的周赛&#xff0c…

SQLserver技巧 年份判断,以及向上想下取整

SELECT [出厂日期],DATEDIFF(month,出厂日期,getdate())*1.0/12 as 使用年限/年 ---------得到的结果实际&#xff08;浮点&#xff09;,cast(DATEDIFF(month,出厂日期,getdate())*1.0/12 as decimal(18,1)) as 使用年限/年 FROM tableA参考&#xff1a; https://blog.csdn.…

这篇文章来告诉你几个实用的视频转文字的方法

相信大家在闲暇之余&#xff0c;都会通过一些网课来提高自己的知识本领吧&#xff01;有的时候在上网课的过程中&#xff0c;会感觉自己做笔记的速度赶不上老师的进度&#xff0c;重复观看又比较麻烦&#xff0c;这时我们就可以借助一些视频转换软件来将视频转换成文字&#xf…

元宇宙产业委共同主席倪健中:发挥元宇宙总部基地优势,探索农业元宇宙发展之路|2022首届海南自贸港(临高)乡村振兴发展论坛

12月12日&#xff0c;2022首届海南自贸港&#xff08;临高&#xff09;乡村振兴发展论坛暨经济合作洽谈周活动在临高开幕。此次活动以“精彩新临高抢滩自贸港”为主题&#xff0c;重点推介“红色”文旅、“黄色”农业、“蓝色”海洋、“绿色”金牌港和“紫色”数字经济组成的五…