vue裡面引入react並相互通訊

假裝做前端發表於2018-08-30
問題: 一個畫圖元件是用react做的,而頁面是用vue來寫的,怎麼掛載,vue應用裡的資料怎麼傳遞到react裡面呢。

react繪圖功能和vue頁面被分別打包成了兩個包。


先來看下效果

檢視樓棟狀態

先來了解下 生命鉤子,需要在vue生命鉤子的mounted裡面呼叫react方法來繪製圖形,可以在react程式碼裡面暴露一個方法,

//react app
import App from './app/kon/index'

window.loadCanvas = function(param) {
  ReactDOM.render(<App 
    projectId={param.projectId} //繪圖元件需要它去請求api
    isEdit={param.type == 'edit'} //圖形有兩種狀態,檢視和編輯狀態
    router={param.router} //在內部繪圖完成可能會做一些vue-router層面的跳轉,所以傳遞
    />, document.getElementById(param.id))
}
複製程式碼

在vue裡面的呼叫

 mounted() {
        // 在react app裡面暴露該方法
        window.loadCanvas({
            type: 'edit',
            id: 'reactApp',
            projectId: this.$route.query.projectId
        })
    }
即vue掛載完成後初始化react元件。
複製程式碼

資料通訊 vue 傳遞到react 先實現一個全域性的訂閱釋出(也可以直接使用backbone裡面的事件模組Event)

utils={
     Event:(function(){
        var clientList={},listen,trigger,remove;

        listen=function(key,fn){
            clientList[key]=clientList[key] ||[];
            clientList[key].push(fn);
        };


        trigger=function(){
            var args=[].slice.call(arguments),
                key=args.shift(),
                fns=clientList[key];
            // 修復bug 不是&&的關係 是或的關係
            if(!fns || !fns.length){
                return;
            }

            for(var i =0,len=fns.length;i<len;i++){
                fns[i].apply(this,args);
            }
        };


        remove=function(key,fn){
            clientList[key]=[];
            // fns=[];
            return;
            if(fns){
                for(var i=0,len=fns.length;i<len;i++){
                    if(fns[i]){
                        fns.splice(i,1);
                    }
                }
            }
        };

        return {
            trigger:trigger,
            listen:listen,
            remove:remove,
            on:listen
        }
    })(),
}
複製程式碼

資料是從vue傳遞到react,所以需要在react裡面訂閱,在vue裡面觸發 先再react繪圖頂級元件裡面訂閱

componentWillMount() {
		// 檢視模式,從頁面獲取事件初始化
		//防止trigger多次
		utils.Event.remove('VMDATA')
		//第一次繪圖初始化
		utils.Event.listen('VMDATA', param => {
			this.initData(param)
		})

		utils.Event.remove('VMUPDATE')
		//監聽vue裡點選切換樓棟時資料變化,此時需要重繪
		utils.Event.listen('VMUPDATE', param=>{
			this.updateData(param)
		})
}
複製程式碼

然後在vue裡面

先獲取資料,再繪製,繪製完後再傳遞資料
let canvasInit = _.after(2, () => {
			utils.hideLoading()
			this.$nextTick(() => {
				window.loadCanvas({
					type: 'show',
					projectId: this.$route.query.projectId,
					id: 'js_canvas',
					router: this.$router
				})
				this.hadShowCanvas = true
				utils.Event.trigger('VMDATA', canvasData)
				this._canvasData = canvasData
			})
		})

複製程式碼

當右側點選按鈕變化時

先進行資料過濾處理,再繪製
	utils.Event.trigger('VMDATA', canvasDataFilter)
複製程式碼

至此,整個從vue到react繪圖搭建好了。

相關文章