Code前端首页关于Code前端联系我们

组件中全局异步任务和生命周期相关问题的解决方法

terry 2年前 (2023-09-08) 阅读数 188 #Vue

异步拿到用户信息 && 页面内mounted执行 == 渲染canvas异步拿到用户信息 && 页面内mounted执行 == 渲染canvas

不知道你是否遇到过这样的场景。该页面应询问用户名和性别并在画布上提供。首次登录时,需要向app.vue发送异步请求来获取。它肯定会被捕获在页面上。不足。您应该监控 vuex 中 userInfo 的变化。如果发现数据已经获取并且执行了附加的hook,就可以渲染画布了。您需要监视这两种状态,然后才能继续执行以下逻辑。但每一页都是这样。显然写起来太麻烦了。

所以我写了一个不错的操作,它可以注册一个异步任务,并在条件满足时自动执行适当的钩子。可以与原生hook结合使用,也可以单独使用。为了您的方便,我希望这个解决方案对大家有所帮助,如果有效请告诉我。

github:github.com/1977474741/…

vue-custom-hooks 它是什么?

  • 可以管理vue组件hook的项。您可以注册一个全局异步任务,并在满足条件时自动在页面上执行相应的钩子。
  • 支持免费使用原生vue hooks创建、安装等。
  • 支持h5、mpvue、传统uni-app

为了什么?

解决了业务页面必须同时监控多个全局状态的问题

来一些真实的场景吧

用户第一次进入小程序时,必须进入onLaunch app.vue获取token和用户信息,然后存储到商店中。现在我们需要创建一个页面,在画布上创建用户头像、昵称等。底线是这两个条件都必须满足。

选项1.监控商店是否收到页面上的用户信息&& DOM Tree是否已创建。
//缺点:比较麻烦,耦合度高,用到的页面都要监听userinfo的改变和dom树渲染完毕,重复性代码多,不利于维护
data(){
    return{
        //任务完成数
        num: 0
    }
},
computed: {
    userInfo: function(){
        return this.$store.state.userInfo
},
watch:{
    userInfo(newval,oldval){
        //监听拿到用户信息了
        if(newval.nickName){
            this.num++;
            if(this.num == 2){
                //可以渲染canvas了
                renderCanvas();
            }
        }
    }
},
mounted(){
    //dom渲染完毕
    this.num++;
    if(this.num == 2){
        //可以渲染canvas了
        renderCanvas();
    }
}
 
选项 2. 在提供的页面 && DOM Tree 上请求用户信息。
//缺点:跟方案1差不多,用到的页面都要写获取用户信息的方法和监听dom树渲染完毕
data(){
    return{
        //任务完成数
        num: 0
    }
},
computed: {
    userInfo: function(){
        return this.$store.state.userInfo
},
methods:{
    getUserInfo(cb){
        //发起请求获取用户信息
        let userinfo = {nickName:'张三'};
        this.$store.commit('userinfo',userinfo);
        cb()
    }
},
created(){
    this.getUserInfo(()=>{
        this.num++;
        if(this.num == 2){
            //可以渲染canvas了
            renderCanvas();
        }
    })
},
mounted(){
    //dom渲染完毕
    this.num++;
    if(this.num == 2){
        //可以渲染canvas了
        renderCanvas();
    }
},
 

使用 vue-custom-hooks 实现上述场景

//第一步,安装插件:
npm install vue-custom-hooks

//第二步,入口文件里注册插件:
import CustomHook from 'vue-custom-hooks';
Vue.use({
    install(Vue) {
        CustomHook.init(Vue,{
             'UserInfo':{
                name:'UserInfo',
                watchKey: '$store.state.userinfo',
                deep: true,
                onUpdate(val){
                    //userinfo里含有nickName则表示命中此钩子
                    return !!val.nickName;
                }
            }
        })
    }
})

//第三步,业务页面里使用插件(任何页面都可以使用,耦合度低,重复性代码少):
onMountedUserInfo(){
    //可以渲染canvas了
    renderCanvas();
}

 

功能说明

  • CustomHook.init

import CustomHook from 'vue-custom-hooks';
CustomHook.init(Vue,diyHooks)
 
  • 对象描述 diyHooks

{
    //1.注册属性监听钩子
    //UserInfo,钩子单名,首字母大写
    'UserInfo':{
        //name,钩子全称,监听属性的话可以和上面的key一致,必填
        name:'UserInfo',
        //watchKey要监听的属性名,属性监听钩子模式必填
        watchKey: '$store.state.userinfo',
        //是否默认命中,非必填
        hit: false,
        //deep是否深度监听,非必填
        deep: true,
        //onUpdate属性改变时执行的callback,用来决定是否要命中此钩子,非必填,缺省值相当于返回了!!val
        onUpdate(val){
            //这里表示userinfo里含有nickName则命中此钩子。注意不可以异步return
            return !!val.nickName;
        }
    },
    
    //2.注册事件监听钩子
    //BeforeMount,钩子单名,首字母大写
    'BeforeMount':{
        //name,原生钩子名,用来命中此钩子,必填
        name:'beforeMount',
        //destroy,相反的钩子名,用来取消命中,事件监听钩子必填
        destroy:'destroyed',
        //是否默认命中,非必填
        hit: false
    }
}
 

如何使用?

export default {
    name: 'Home',
    created(){
        //数据初始化完成
    },
    mounted(){
        //dom渲染完成
    },
    onCreatedUserInfo(){
        //数据初始化完成 && 获取用户信息完成
    },
    onMountedUserInfo(){
        //dom渲染完成 && 获取用户信息完成
    }
}
 

鱼钩使用规则

`on{UserInfo}{BeforeMount}{Login}{Position}...` //所有注册好的钩子都可以随意搭配,排列顺序不影响钩子执行,都是 && 的关系
 

已注册原挂钩

Launch、Created、Load、Attached、Show、Mounted、Ready
//如需其他的钩子可自行注册
 

二维码演示

left image description hereleft image description here

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门