vue3:vue2中protoType更改为config.globalProperties问题

 更新时间:2022年09月09日 09:05:40   作者:Mosowe  
这篇文章主要介绍了vue3:vue2中protoType更改为config.globalProperties问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

protoType替换为config.globalProperties

原文地址

在main.js中:

vue2

Vue.prototype.$verson = '1.0.0'

使用

this.$verson

vue3

Vue.config.globalProperties.$verson = '1.0.0'

使用

<script setup lang="ts">
import {getCurrentInstance} from 'vue'
console.log(getCurrentInstance().appContext.config.globalProperties.$verson)
</script>

Vue3 vs Vue2

Vue3 的新组件

Fragment

Vue2 中:组件必须有一个根标签

Vue3 中:可以没有根标签,内部会添加根标签 <fragment> </fragment>

好处:减少标签层级,减少内存消耗

<template>
    <h1>App</h1>
    <p>superman</p>
</template>
<script>
export default { name: "App" };
</script>

Teleport

用于将组件的 HTML 结构移动到指定位置

用法:

① 用 Teleport 标签将需要移动的 HTML 结构包裹住

② 设置 to 属性,属性值为 选择器,以指定移动到的位置

默认情况下,子组件的 HTML 结构会显示到父组件的 HTML 结构里面;

使用 Teleport 标签包裹子组件的 HTML 标签,则能将该 HTML 结构显示到指定的位置 

<template>
    <div class="box">
        <h1>App</h1>
        <button @click="bol = !bol">显示 / 隐藏</button>
        <Son v-if="bol" />
    </div>
</template>
<script>
import { ref } from "vue";
import Son from "./components/Son.vue";
export default {
    name: "App",
    components: { Son },
    setup() {
        let bol = ref(false);
        return { bol };
    },
};
</script>
<style>
.box {
    width: 200px;
    height: 200px;
    background: palevioletred;
    position: relative;
}
</style>
<template>
    <!-- 默认情况下,显示到 .box 里面 -->
    <h2>Son</h2>
    <!-- 通过 Teleport 标签,将 HTML 结构显示到 body 里面 -->
    <Teleport to="body">
        <h2>Teleport Son</h2>
    </Teleport>
</template>
<script>
export default { name: "Son" };
</script>

Suspense

等待异步组件时,渲染一些额外的内容,提升用户体验感

用法:

① 在父组件中,异步引入组件:defineAsyncComponent + 懒加载

② 在子组件中,配置 Suspense 标签

③ 在 Suspense 标签内,用 template 标签设置具名插槽

default 插槽的内容:为异步引入的组件

fallback 插槽的内容:为加载时显示的内容

此时,异步引入的组件中 setup 可以是 async 函数 

<template>
    <div class="box">
        <h1>App</h1>
        <Suspense>
            <!-- 需要显示的异步组件 -->
            <template v-slot:default>
                <Son></Son>
            </template>
            <!-- 异步组件显示之前,暂时先显示的内容 -->
            <template #fallback>
                加载中...
            </template>
        </Suspense>
    </div>
</template>
<script>
// 静态引入
// import Son from "./components/Son.vue"; 
// 异步引入
import { defineAsyncComponent } from 'vue';
const Son = defineAsyncComponent(() => import("./components/Son.vue"));
export default {
    name: "App",
    components: { Son },
};
</script>
<template>
    <h2>Son: {{ p }}</h2>
</template>
<script>
export default {
    name: "Son",
    // 此时 setup 也可以是 async 函数
    async setup() {
        let p = await new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve("superman")
            }, 1000);
        });
        return { p };
    }
};
</script>

文件对比

main.js

Vue2

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
    router,
    store,
    render: h => h(App)
}).$mount('#app')

Vue3

引入的不再是 Vue 构造函数,而是工厂函数 createApp:

构造函数:通过 new 关键字调用,首字母大写

工厂函数:直接调用,首字母小写

createApp 返回:应用实例对象 (相当于 Vue2 中的 vm,但比 vm 轻)

可以在 createApp 之后链式调用其它方法

import { createApp } from 'vue' // 引入 createApp 方法
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app') // 链式调用

store 文件

Vue2

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
    state: {},
    mutations: {},
    actions: {},
    modules: {}
})

Vue3

import { createStore } from 'vuex' // 引入 createStore 方法
export default createStore({
    state: {},
    mutations: {},
    actions: {},
    modules: {}
})

Vuex 的使用

先配置好 store 文件:

import { createStore } from 'vuex'
export default createStore({
    state: {
        name: "superman",
        arr: [1, 2, 3]
    },
    mutations: {
        muModify(state, val) {
            console.log("commit muModify", val)
            state.name += val
        }
    },
    actions: {
        acModify(context, val) {
            console.log("dispatch acModify", val)
            context.commit("muModify", val)
        }
    },
    getters: {
        getArr(state) {
            return state.arr.map(item => item * 2)
        }
    },
    modules: {}
})

Vue3 中需要通过 useStore 方法使用 vuex

<template>
    <p>普通使用:</p>
    <p>$store.state.name: {{ $store.state.name }}</p>
    <p>$store.state.arr: {{ $store.state.arr }}</p>
    <p>$store.getters.getArr: {{ $store.getters.getArr }}</p>
    <hr />
    <p>Vue 3:</p>
    <p>name: {{ name }}</p>
    <p>arr: {{ arr }}</p>
    <p>getArr: {{ getArr }}</p>
    <hr />
    <button @click="coModify">coModify name</button> |
    <button @click="diModify">diModify name</button>
</template>
<script>
import { useStore } from "vuex";
export default {
    name: "App",
    setup() {
        // 通过 useStore 使用 Vuex
        const store = useStore();
        // 获取数据
        let name = store.state.name;
        let arr = store.state.arr;
        let getArr = store.getters.getArr;
        // 调用 dispatch 方法
        function diModify() {
            store.dispatch("acModify", "(Actions)");
        }
        // 调用 commit 方法
        function coModify() {
            store.commit("muModify", "(Mutations)");
        }
        return { name, arr, getArr, coModify, diModify };
    },
};
</script>

但是,通过该方法获取的数据不是响应式的

响应式数据设置如下:需要配合 computed 方法使用

let name = computed(() => store.state.name);
let arr = computed(() => store.state.arr);
let getArr = computed(() => store.getters.getArr);

router 文件

Vue2

import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [{
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue')
    }
]
const router = new VueRouter({
    mode: 'history', // 设置路由模式为 history
    base: process.env.BASE_URL, // 根据 webpack 环境,设置 [根路径]
    routes
})
export default router

Vue3

import {
    createRouter, // 引入 createRouter 方法
    createWebHistory // 引入 createWebHistory 方法
} from 'vue-router'
import Home from '../views/Home.vue'
const routes = [{
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue')
    }
]
const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes
})
export default router
vue-router 的使用

先配置 router 文件

import {
    createRouter,
    createWebHistory
} from 'vue-router'
import Home from '../views/Home.vue'
const routes = [{
        path: '/',
        name: 'Home',
        component: Home
    },
    {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue')
    }
]
const router = createRouter({
    history: createWebHistory(process.env.BASE_URL),
    routes
})
export default router

Vue3 中需要通过 useRoute 方法使用 vue-router

<template>
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
    <router-view />
</template>
<script>
export default {
    name: "App",
};
</script>
<template>
    <h1>About</h1>
</template>
<script>
import {
    useRoute,
    useRouter,
    onBeforeRouteLeave,
    onBeforeRouteUpdate,
} from "vue-router";
export default {
    name: "About",
    setup() {
        // 当前路由对象
        let route = useRoute();
        console.log("route", route);
        // 总路由对象
        let router = useRouter(router);
        console.log("router", router);
        // 路由守卫
        onBeforeRouteLeave(() => {
            console.log("onBeforeRouteLeave:离开路由时触发");
        });
        onBeforeRouteUpdate(() => {
            console.log("onBeforeRouteUpdate:复用路由时触发");
        });
        return {};
    },
};
</script>
<template>
    <h1>Home</h1>
</template>
<script>
export default { name: "Home" };
</script>

全局 API

在 Vue3 中,全局和内部 API 都经过了重构

全局 API 现在只能作为 ES 模块构建的命名导出进行访问

import { nextTick } from 'vue'
nextTick(() => {
    // 一些和DOM有关的东西
})

Vue.XXXapp.XXX

全局 directive

Vue2 - Vue.directive("自定义指令名", 配置对象)
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
Vue.directive("focus", {
    bind() {
        console.log("指令与元素绑定时触发");
    },
    inserted(el) {
        console.log("指令所在元素插入页面时触发");
        el.focus();
    },
    update(el) {
        console.log("模板重新渲染时触发");
        el.focus();
    }
});
new Vue({ render: h => h(App) }).$mount('#app')

也可以使用简写(回调函数执行完后,DOM 才会插入到页面中):

Vue.directive("focus", (el, msg) => {
    console.log(el, msg); // el:挂载的元素;val:挂载的信息
    console.log(msg.value); // 获取指令的属性值
});

Vue3 - app.directive("自定义指令名", 配置对象)

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 自定义指令,指令具有一组生命周期钩子:
app.directive('myIns', {
    // 在绑定元素的 attribute 或事件监听器被应用之前调用
    created() {},
    // 在绑定元素的父组件挂载之前调用
    beforeMount() {},
    // 在绑定元素的父组件挂载之后调用
    mounted() {},
    // 在包含组件的 VNode 更新之前调用
    beforeUpdate() {},
    // 在包含组件的 VNode 及其子组件的 VNode 更新之后调用
    updated() {},
    // 在绑定元素的父组件卸载之前调用
    beforeUnmount() {},
    // 在绑定元素的父组件卸载之后调用
    unmounted() {}
});
app.mount('#app')

钩子函数接收 2 个参数:

  • el:指令绑定到的元素,可用于直接操作 DOM。eg:el.focus()
  • binding:配置对象
  • instance:使用指令的组件实例
  • value:传递给指令的值
  • oldValue:先前的值,仅在 beforeUpdate 和 updated 中可用。无论值是否有更改都可用
  • arg:传递给指令的参数(如果有的话)
  • eg:v-my-directive:foo 中,arg 为 "foo"。
  • modifiers:修饰符对象(如果有的话)
  • eg:v-my-directive.foo.bar 中,修饰符对象为 {foo: true,bar: true}
  • dir:配置对象本身

全局属性

  • 全局属性:在任何组件中都可以访问
  • 与组件的属性发生命名冲突时,组件的属性优先级更高

Vue2 - Vue.prototype

import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
Vue.prototype.$myData = "superman" // 设置全局属性
new Vue({ render: h => h(App) }).$mount('#app')

Vue3 - app.config.globalProperties

import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
app.config.globalProperties.$myData = "superman" // 设置全局属性
app.mount('#app')

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • vue router 用户登陆功能的实例代码

    vue router 用户登陆功能的实例代码

    这篇文章主要介绍了vue router 用户登陆功能的实例代码,主要用到H5中的会话存储(sessionStorage)、vue-router路由前置操作、路由元信息(meta)等知识点,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2019-04-04
  • Vue 2.5.2下axios + express 本地请求404的解决方法

    Vue 2.5.2下axios + express 本地请求404的解决方法

    下面小编就为大家分享一篇Vue 2.5.2下axios + express 本地请求404的解决方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • vue watch监听对象及对应值的变化详解

    vue watch监听对象及对应值的变化详解

    下面小编就为大家分享一篇vue watch监听对象及对应值的变化详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • elementui之el-table如何通过v-if控制按钮显示与隐藏

    elementui之el-table如何通过v-if控制按钮显示与隐藏

    这篇文章主要介绍了elementui之el-table如何通过v-if控制按钮显示与隐藏问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • 详解VUE 数组更新

    详解VUE 数组更新

    这篇文章主要介绍了VUE 数组更新问题,文中给大家介绍了vue如何监听数据的变化的 ,需要的朋友可以参考下
    2017-12-12
  • vue通过vue-lazyload实现图片懒加载的代码详解

    vue通过vue-lazyload实现图片懒加载的代码详解

    这篇文章主要给大家介绍了vue通过vue-lazyload实现图片懒加载,文中通过代码示例给大家介绍的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-02-02
  • 解决vue-router 切换tab标签关闭时缓存问题

    解决vue-router 切换tab标签关闭时缓存问题

    这篇文章主要介绍了解决vue-router 切换tab标签关闭时缓存问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • Vue自定义指令写法与个人理解

    Vue自定义指令写法与个人理解

    VUE指令是什么,VUE自定义指令又是什么,下面就和大家分享一下个人对它们的理解
    2019-02-02
  • Vue 3 中使用 vue-router 进行导航与监听路由变化的操作

    Vue 3 中使用 vue-router 进行导航与监听路由变化的操作

    在Vue3中,通过useRouter和useRoute可以方便地实现页面导航和路由变化监听,useRouter允许进行页面跳转,而useRoute结合watch可以根据路由变化更新组件状态,这些功能为Vue3应用增加了灵活性和响应性,使得路由管理更加高效
    2024-09-09
  • 关于vue中媒体查询不起效的原因总结

    关于vue中媒体查询不起效的原因总结

    这篇文章主要介绍了关于vue中媒体查询不起效的原因总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09

最新评论