釘釘微應用 開發體驗及心得

開始調研

主要仍是看釘釘的官方文檔和論壇,釘釘推薦使用saltUI和saltRouter進行開發微應用,可是看了這2個東西的源碼後,感受沒封裝什麼東西,主要的功能仍是集中在釘釘的dingtalk.js中,因此我的認爲不必用它推薦的這2個東西。vue

框架選擇

做爲一個vue的忠實粉絲,此次也確定想用vue進行開發,考慮到vue2.0尚未很好的移動端UI框架,因此此次試用了更成熟的vue1.0的ui框架vux,而後微應用其實對應用狀態管理的要求仍是比較高的,因此也用了vuex來管理應用狀態。ios

微應用流程

咱們使用的是免登錄流程以下git

  1. 它的入口網頁會自動傳appid,corpid,suiteKey這3個參數在url上面,經過這3個參數去本身的服務器獲取到dd.config須要用的參數.github

  2. 而後在dd.ready中設置和獲取一些全局的釘釘屬性,好比 設置左上角返回鍵的回調,獲取容器的版本信息(用來判斷能不能調用某些jsapi)vuex

  3. 再初始化vue,配置vue插件什麼的axios

  4. 最後判斷js.config是否成功,而後dispath到vuex中api

代碼詳解

對比上面流程的1. 2. 3. 4. 的代碼服務器

getConfig() //1.經過url上的3個參數,獲取本身服務器上的配置信息
    .then((data)=>{ 
        ddConfig = data;
        dd.config(ddConfig); //1.初始化釘釘的jssdk
    })
    .then(ddIsReady) //2.作一些釘釘的全局設置
    .then(initVue) //3.初始化vue
    .then(()=>{
        document.querySelector('#init-loading').remove(); //移除加載動畫
        console.log('init vue 完成')
        setTimeout(()=>{
            if(ddConfig != null){
                commit('DDCONFIG_SUCCESS', ddConfig)  //4.通知vuex改變應用功能狀態
            }else{
                commit('DDCONFIG_ERROR', false);  //4.通知vuex改變應用功能狀態
            }
        },300)
    })

getConfig

function getConfig() {
    return Q.Promise((success, error)=>{
        axios.get(env.API_HOST+'/auth/getConfig', {
            params: {
                corpid: getParamByName('corpid')||'',
                appid: getParamByName('appid')||'',
                suitekey: getParamByName('suiteKey')||'',
                paramUrl: document.URL
            },
            timeout: 2000,
        }).then(function (response) {
            if(response.status == 200 && response.data.code == 200){
                let res = response.data.result;
                let ddConfig = {
                    agentId: res.agentId, // 必填,微應用ID
                    corpId: res.corpId,//必填,企業ID
                    timeStamp: res.timeStamp, // 必填,生成簽名的時間戳
                    nonceStr: res.nonceStr, // 必填,生成簽名的隨機串
                    signature: res.signature, // 必填,簽名
                    type:0,   //選填。0表示微應用的jsapi,1表示服務窗的jsapi。不填默認爲0。該參數從dingtalk.js的0.8.3版本開始支持
                    jsApiList : [
                        'runtime.info',
                        'runtime.permission.requestAuthCode',
                        'runtime.permission.requestOperateAuthCode', //反饋式操做臨時受權碼

                        'biz.alipay.pay',
                        'biz.contact.choose',
                        'biz.contact.complexChoose',
                        'biz.contact.complexPicker',
                        'biz.contact.createGroup',
                        'biz.customContact.choose',
                        'biz.customContact.multipleChoose',
                        'biz.ding.post',
                        'biz.map.locate',
                        'biz.map.view',
                        'biz.util.openLink',
                        'biz.util.open',
                        'biz.util.share',
                        'biz.util.ut',
                        'biz.util.uploadImage',
                        'biz.util.previewImage',
                        'biz.util.datepicker',
                        'biz.util.timepicker',
                        'biz.util.datetimepicker',
                        'biz.util.chosen',
                        'biz.util.encrypt',
                        'biz.util.decrypt',
                        'biz.chat.pickConversation',
                        'biz.telephone.call',
                        'biz.navigation.setLeft',
                        'biz.navigation.setTitle',
                        'biz.navigation.setIcon',
                        'biz.navigation.close',
                        'biz.navigation.setRight',
                        'biz.navigation.setMenu',
                        'biz.user.get',

                        'ui.progressBar.setColors',

                        'device.base.getInterface',
                        'device.connection.getNetworkType',
                        'device.launcher.checkInstalledApps',
                        'device.launcher.launchApp',
                        'device.notification.confirm',
                        'device.notification.alert',
                        'device.notification.prompt',
                        'device.notification.showPreloader',
                        'device.notification.hidePreloader',
                        'device.notification.toast',
                        'device.notification.actionSheet',
                        'device.notification.modal',
                        'device.geolocation.get',


                    ] // 必填,須要使用的jsapi列表,注意:不要帶dd。
                }
                success(ddConfig)
            }else{
                error({errCode:-2,msg:'接口請求失敗'})
            }
        }).catch(function (err) {
            error({errCode:-2,msg:'接口請求失敗'})
        });
    })

}

ddIsReady

function ddIsReady() {
    return Q.Promise((success, error)=>{
        let timeout = setTimeout(()=>{
            error({errCode:-1,msg:'dd.ready初始化超時'});
        },2000)
        dd.ready(function(){
            console.log('初始化釘釘');
            clearTimeout(timeout)

            //設置返回按鈕
            dd.biz.navigation.setLeft({
                show: true,//控制按鈕顯示, true 顯示, false 隱藏, 默認true
                control: true,//是否控制點擊事件,true 控制,false 不控制, 默認false
                showIcon: true,//是否顯示icon,true 顯示, false 不顯示,默認true; 注:具體UI以客戶端爲準
                text: '返回',//控制顯示文本,空字符串表示顯示默認文本
                onSuccess : function(result) {
                    //若是control爲true,則onSuccess將在發生按鈕點擊事件被回調
                    console.log('點擊了返回按鈕');
                    window.history.back();
                },
                onFail : function(err) {}
            });
            //獲取容器信息
            dd.runtime.info({
                onSuccess: function(result) {
                    window.ability = parseInt(result.ability.replace(/\./g,''));
                    console.log('容器版本爲'+window.ability)
                },
                onFail : function(err) {}
            })

            success(true)
        });
        dd.error(function(err){
            clearTimeout(timeout)
            /**
             {
                message:"錯誤信息",//message信息會展現出釘釘服務端生成簽名使用的參數,請和您生成簽名的參數做對比,找出錯誤的參數
                errorCode:"錯誤碼"
             }
             **/
            console.error('dd error: ' + JSON.stringify(err));
            error({errCode:-1,msg:'dd.error配置信息不對'})
        });
    })
}

initVue

function initVue() {
    return Q.Promise((success, error)=>{

        Vue.use(Router)
        Vue.use(bbPlugin)
        Vue.use(ddPlugin)

        let router = new Router({
            transitionOnLoad: false
        })
        router.map({
            [env.BASE_PATH] : {
                component: function(resolve){
                    require.ensure([], function() {
                        let route = require('./page/home/route').default;
                        resolve(route);
                    },'home')
                },
                subRoutes: {
                    '/': {
                        component: function (resolve) {
                            require.ensure([], function () {
                                let route = require('./page/home/index/route').default;
                                resolve(route);
                            },'index')
                        }
                    },
                    '/member' : {
                        component: function(resolve){
                            require.ensure([], function() {
                                let route = require('./page/home/member/route').default;
                                resolve(route);
                            },'member')
                        }
                    },
                }
            },
            [env.BASE_PATH+'/user/sign_in'] : {
                component: function (resolve) {
                    require.ensure([], function () {
                        let route = require('./page/user-sign-in/route').default;
                        resolve(route);
                    }, 'user-sign-in')
                }
            },
            [env.BASE_PATH+'/user/bind'] : {
                component: function (resolve) {
                    require.ensure([], function () {
                        let route = require('./page/user-bind-mobile/route').default;
                        resolve(route);
                    }, 'user-bind-mobile')
                }
            }
        });
        router.redirect({
            '*': env.BASE_PATH
        });
        let history = window.sessionStorage
        history.clear()
        let historyCount = history.getItem('count') * 1 || 0
        history.setItem('/', 0)

        router.beforeEach(({ to, from, next }) => {
            const toIndex = history.getItem(to.path)
            const fromIndex = history.getItem(from.path)
            if (toIndex) {
                if (toIndex > fromIndex || !fromIndex) {
                    commit('UPDATE_DIRECTION', 'forward')
                } else {
                    commit('UPDATE_DIRECTION', 'reverse')
                }
            } else {
                ++historyCount
                history.setItem('count', historyCount)
                to.path !== '/' && history.setItem(to.path, historyCount)
                commit('UPDATE_DIRECTION', 'forward')
            }
            commit('UPDATE_LOADING', true)


            setTimeout(()=>{
                try {
                    //設置右側按鈕
                    dd.biz.navigation.setRight({
                        show: false,//控制按鈕顯示, true 顯示, false 隱藏, 默認true
                    });
                }catch (err){
                    console.error(err);
                }

                next();
            }, 10)
        })
        router.afterEach(() => {
            commit('UPDATE_LOADING', false)
        })
        sync(store, router)
        router.start(App, '#app')

        FastClick.attach(document.body)

        success()
    })
}

而後就能夠愉快的寫業務代碼啦

怎麼能不開源呢?我只是把不少開源項目的代碼拼到了一塊兒,請諒解... github demosession

相關文章
相關標籤/搜索