想知道Vue3与Vue2的区别?五千字教程助你快速上手Vue3!(下)
EventBus/mitt
兄弟组件通信可以通过一个事件中心EventBus实现,既新建一个Vue实例来进行事件的监听,触发和销毁。
在Vue3中没有了EventBus兄弟组件通信,但是现在有了一个替代的方案mitt.js
,原理还是 EventBus
- 选项式API
//组件1 template> div> button @click="sendMsg"> 传值/button> /div> /template> script> import Bus from './bus.js' export default { data(){ return { msg:'子组件元素' } } , methods:{ sendMsg(){ Bus.$emit('sendMsg','兄弟的值') } } } /script> //组件2 template> div> 组件2 /div> /template> script> import Bus from './bus.js' export default { created(){ Bus.$on('sendMsg',(val)=> { console.log(val); //兄弟的值 } ) } } /script> //bus.js import Vue from "vue" export default new Vue()
- 组合式API
首先安装mitt
npm i mitt -S
然后像Vue2中bus.js
一样新建mitt.js
文件
mitt.js
import mitt from 'mitt' const Mitt = mitt() export default Mitt
//组件1 template> button @click="sendMsg"> 传值/button> /template> script> import { defineComponent } from "vue"; import Mitt from './mitt.js' export default defineComponent({ setup() { const sendMsg = () => { Mitt.emit('sendMsg','兄弟的值') } return { sendMsg } } , } ); /script> //组件2 template> div> 组件2 /div> /template> script> import { defineComponent, onUnmounted } from "vue"; import Mitt from './mitt.js' export default defineComponent({ setup() { const getMsg = (val) => { console.log(val); //兄弟的值 } Mitt.on('sendMsg', getMsg) onUnmounted(() => { //组件销毁 移除监听 Mitt.off('sendMsg', getMsg) } ) } , } ); /script>
- setup语法糖
//组件1 template> button @click="sendMsg"> 传值/button> /template> script setup> import Mitt from './mitt.js' const sendMsg = () => { Mitt.emit('sendMsg', '兄弟的值') } /script> //组件2 template> div> 组件2 /div> /template> script setup> import { onUnmounted } from "vue"; import Mitt from './mitt.js' const getMsg = (val) => { console.log(val); //兄弟的值 } Mitt.on('sendMsg', getMsg) onUnmounted(() => { //组件销毁 移除监听 Mitt.off('sendMsg', getMsg) } ) /script>
v-model和sync
v-model大家都很熟悉,就是双向绑定的语法糖。这里不讨论它在input标签的使用;只是看一下它和sync在组件中的使用
我们都知道Vue中的props是单向向下绑定的;每次父组件更新时,子组件中的所有props都会刷新为最新的值;但是如果在子组件中修改 props ,Vue会向你发出一个警告(无法在子组件修改父组件传递的值);可能是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得混乱难以理解。
但是可以在父组件使用子组件的标签上声明一个监听事件,子组件想要修改props的值时使用$emit触发事件并传入新的值,让父组件进行修改。
为了方便vue就使用了v-model
和sync
语法糖。
- 选项式API
//父组件 template> div> !-- 完整写法 Child @update:changePval="msg=$event" /> --> Child :changePval.sync="msg" /> { { msg} } /div> /template> script> import Child from './Child' export default { components: { Child } , data(){ return { msg:'父组件值' } } } /script> //子组件 template> div> button @click="changePval"> 改变父组件值/button> /div> /template> script> export default { data(){ return { msg:'子组件元素' } } , methods:{ changePval(){ //点击则会修改父组件msg的值 this.$emit('update:changePval','改变后的值') } } } /script>
- setup语法糖
因为使用的都是前面提过的知识,所以这里就不展示组合式API的写法了
//父组件 template> div> !-- 完整写法 Child @update:changePval="msg=$event" /> --> Child v-model:changePval="msg" /> { { msg} } /div> /template> script setup> import Child from './Child' import { ref } from 'vue' const msg = ref('父组件值') /script> //子组件 template> button @click="changePval"> 改变父组件值/button> /template> script setup> import { defineEmits } from 'vue'; const emits = defineEmits(['changePval']) const changePval = () => { //点击则会修改父组件msg的值 emits('update:changePval','改变后的值') } /script>
总结
vue3中移除了sync的写法,取而代之的式v-model:event的形式
其v-model:changePval="msg"
或者:changePval.sync="msg"
的完整写法为@update:changePval="msg=$event"
。
所以子组件需要发送update:changePval
事件进行修改父组件的值
路由
vue3和vue2路由常用功能只是写法上有些区别
- 选项式API
template> div> button @click="toPage"> 路由跳转/button> /div> /template> script> export default { beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 next() } , beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 next() } , beforeRouteLeave ((to, from, next)=> { //离开当前的组件,触发 next() } ), beforeRouteLeave((to, from, next)=> { //离开当前的组件,触发 next() } ), methods:{ toPage(){ //路由跳转 this.$router.push(xxx) } } , created(){ //获取params this.$route.params //获取query this.$route.query } } /script>
- 组合式API
template> div> button @click="toPage"> 路由跳转/button> /div> /template> script> import { defineComponent } from 'vue' import { useRoute, useRouter } from 'vue-router' export default defineComponent({ beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 next() } , beforeRouteLeave ((to, from, next)=> { //离开当前的组件,触发 next() } ), beforeRouteLeave((to, from, next)=> { //离开当前的组件,触发 next() } ), setup() { const router = useRouter() const route = useRoute() const toPage = () => { router.push(xxx) } //获取params 注意是route route.params //获取query route.query return { toPage } } , } ); /script>
- setup语法糖
我之所以用beforeRouteEnter
作为路由守卫的示例是因为它在setup
语法糖中是无法使用的;大家都知道setup
中组件实例已经创建,是能够获取到组件实例的。而beforeRouteEnter
是再进入路由前触发的,此时组件还未创建,所以是无法用在setup
中的;如果想在setup语法糖中使用则需要再写一个script
如下:
template> div> button @click="toPage"> 路由跳转/button> /div> /template> script> export default { beforeRouteEnter(to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 next() } , } ; /script> script setup> import { useRoute, useRouter,onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router' const router = useRouter() const route = useRoute() const toPage = () => { router.push(xxx) } //获取params 注意是route route.params //获取query route.query //路由守卫 onBeforeRouteUpdate((to, from, next)=> { //当前组件路由改变后,进行触发 next() } ) onBeforeRouteLeave((to, from, next)=> { //离开当前的组件,触发 next() } ) /script>
写在最后
通过以上写法的对比会发现setup语法糖的形式最为便捷而且更符合开发者习惯;未来Vue3的开发应该会大面积使用这种形式。目前Vue3已经成为了Vue的默认版本,后续维护应该也会以Vue3为主;所以还没开始学习Vue3的同学要抓紧了!
Vue3文档地址
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: 想知道Vue3与Vue2的区别?五千字教程助你快速上手Vue3!(下)
本文地址: https://pptw.com/jishu/340479.html