skysowe
skysowe
  • 发布:2019-06-06 10:06
  • 更新:2020-12-07 15:41
  • 阅读:8529

Uni-App微信小程序页面间通信的HOOK方式

分类:uni-app

过去两年多一直在H5+环境里开发,刚接触uni-app不久,在h5+里可以方便的通过

WebviewObject plus.webview.create( url, id, styles, extras );

里的extras传递参数给其他页面,也可以通过

var index_main = plus.webview.getWebviewById("index_main");  
index_main.evalJS('update_bill_badge_num()');

来调用已经打开的页面上的方法,或者定义一个接收参数的函数,把参数传递到已经打开的页面里

到了uni-app里的小程序,小的一些参数我可以通过/page/home/home?abc=123这种方式,或者通过LocalStoreage来传递,但是如果是比较大的json,通过第一种方式肯定不行,通过LS方式又太慢了,通过Vue.protoype.xxx来挂载一些常量还可以,变量是没用的,在这个页里修改了,在另外一个页面里还是原来的值。

我在网上看到这篇文章《微信小程序页面间通信的5种方式》https://segmentfault.com/a/1190000008895441 里的方式五:通过hack方法直接调用通信页面的方法,感觉这不就是H5+里的通过webview来传值的方式吗?

然后我就在微信小程序的开发环境里实验成功了

微信小程序里:首先定义了一个pages.js文件,在小程序根目录新建了一个plugin目录,然后放在里面
====================
pages.js的内容:

// plugin/pages.js  
// 缓存pageModel,一个简要实现  

export default class PM {  

    constructor() {  
        this.$$cache = {};  
    }  

    add(pageModel) {   
        let pagePath = this._getPageModelPath(pageModel);   

        this.$$cache[pagePath] = pageModel;   
    }   

    get(pagePath) {   
        return this.$$cache[pagePath];   
    }   

    delete(pageModel) {   
        try {   
            delete this.$$cache[this._getPageModelPath(pageModel)];   
        } catch (e) {   
        }   
    }   

    _getPageModelPath(page) {   
        // 关键点   
        return page.__route__;   
    }  

}

====================
然后在小程序的app.js里引入:

//app.js  
import PageModel from './plugin/pages.js'; //引入  
App({  

    pages: new PageModel(), //挂载一个pages对象   

    onLaunch: function () {  
    },  

    globalData: {  
        userInfo: null  
    }  

})

====================
在页面A里:

// pageA  
let app = getApp();  
Page({  
    data: {  
        helloMsg: 'hello from PageA'  
    },  
    onLoad() {   
        //加入页面缓存对象   
        app.pages.add(this);   

        console.log('Page A');   
    },   
    onShow(){   
        console.log(this.data.helloMsg);   
    },   

    gotoC() {   
        wx.navigateTo({   
            url: '/pages/home/home'   
        });   
    },   

    sayHello(msg) {   
        this.setData({   
            helloMsg: msg   
        });   
    },   

    writeHello(msg){   
        console.log(msg);   
    }  

});

====================
然后在页面C里:

//pageC  
let app = getApp();  
Page({  

    onLoad(){   
        console.log('Page C');   
        this.doSomething();   
    },   

    doSomething() {   

        console.log('do PageC method\n\n');   

        // 见证奇迹的时刻   
        let data_msg = app.pages.get('pages/index/index').data.helloMsg;   

        console.log('------获取A的数据------');   
        console.log( data_msg );   
        console.log('----------------------\n\n');   

        console.log('------改变A的数据------');   
        app.pages.get('pages/index/index').sayHello('hello from PageC');   
        console.log('----------------------\n\n');   

        console.log('------调用A的方法------');   
        app.pages.get('pages/index/index').writeHello('PageC call PageA method!');   
        console.log('----------------------\n\n');   

    }  

});

在页面C里成功获取了页面A的变量,还能调用页面A的方法,如果改变了页面A的变量,,在从页面C回到页面A时,如果显示这个被修改的变量,可以看到变量内容的确被修改了。看到这个实验的结果,我喜出望外,打算把它引入到uni-app中:

一开始我就想仿照微信小程序的方式:
====================
在main.js里

import Vue from 'vue'  
import App from './App'  
import store from './store'  
import PageModel from './pages.js'; //引入  

//省略其他内容  

App.mpType = 'app'  

const app = new Vue({  

    //加入PageModel   
    pages: new PageModel(),   

    ...App  

})  
app.$mount()

====================
又或者放在App.vue里:

<script>  

import PageModel from './pages.js';   

export default {   

    //加入PageModel   
    pages: new PageModel(),   

    onLaunch: function() {   
        console.log('App Launch')   
    },   
    onShow: function() {   
        console.log('App Show')   
    },   
    onHide: function() {   
        console.log('App Hide')   
    }   
}  

</script>  

<style>  
/* 每个页面公共css */  
</style>

然后在PageA里:
var app = getApp();
app.pages.add(this);
两种方法都不行,都报错误,应该是没有正确的把pages挂载到app上去。

console.log( app );
发现其实还是挂载成功了的,在很深的层里:
这样是成功的

app.$vm.$options.pages.add(this);  
console.log( app.$vm.$options.pages );

在PageC里:

var page_index_obj = app.$vm.$options.pages.get('pages/index/index');  
var page_index_obj_index_data = page_index_obj._data.index_data;  
console.log( page_index_obj_index_data )

我对uni-app不太熟悉,对Vue也只是刚开始学习使用,然后搜到社区里一篇文章《getApp() 挂载实例方法》https://ask.dcloud.net.cn/article/35810 ,应该就是我想要的东西,但是说的太模糊了,dcloud的源码实在太长了,看不太懂,直接加到hooks也是不行的,能否指教一下,怎么把自己写的对象,挂载上去。

const hooks = [  
    'onHide',  
    'onError',  
    'onPageNotFound',  
    'onUniNViewMessage',  
    //'pages', //无效  
];

我现在可以实现数据的传递了,但是下面这样的写法,实在是有点丑陋

app.$vm.$options.pages.add(this);  
app.$vm.$options.pages.get('pages/index/index')._data.index_data;‘

另外记得在页面的onUnload里,记得要从页面栈里删除当前对象

        onUnload(){  
            app.$vm.$options.pages.delete(this);  
        },

PS.我已经在项目里使用了上述方法了,相当于在app.$vm.$options.pages里建了一个栈,而且里面的数据和方法都是可以调用的,,比如关闭当前页面的时候,把本页的数据传递到上一个页面里,不知道大家还有更好的方法~

我回复了上文作者,一直没回应我,可能是太忙了,上次文章也没排版好,这次重发一遍。

1 关注 分享
yzdemo

要回复文章请先登录注册

1***@qq.com

1***@qq.com

我是挂到了globalData上
2020-12-07 15:41
七分道道

七分道道

收藏了,感谢楼主分享
2019-06-10 17:18