記:使用vue全家桶 + vux組件庫 打包成 dcloud 5+ app 開發過程當中遇到的問題

vue-cli 版本:2.9.6  css

webpack 版本:3.6.0html

 

1. vue-cli 安裝好以後,不是自動打開默認瀏覽器vue

在 config文件夾 ---> dev選項中,有個 autoOpenBrowser 。把它置爲 true 便可。node

 

2. 使用less(或者sass)全局變量webpack

原由: 由於想定義一些經常使用的工具樣式。相似:超過一行隱藏字體並用省略號顯示,清除浮動,主題顏色等。就考慮不用每一個頁面都引入,能直接使用定義的工具樣式。es6

  第一步: 安裝  npm install sass-resources-loader --save-dev 對的,你沒有看錯,要使用less全局變量,就要安裝 sass-resources-loader 這個包web

  第二步: 配置:找到build文件夾下面的utils.js 找到  exports.cssLoaders  中的最下面的 return {},而後在less配置項中配置如下代碼vuex

配置前:vue-cli

return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
} 

配置後:npm

return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less').concat({ 
      loader: 'sass-resources-loader', 
      options: { 
          resources: path.resolve(__dirname, '../src/assets/css/public.less') 
      } 
    }),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
}

(1) 配置的 less文件路徑就是你本身的 工具樣式 less 文件路徑。用相對路徑

(2) 若是是 想要使用 sass的 工具樣式。只須要在 一樣配置 sass 的地方,後面添加 concat 便可。內容也是同樣,除了工具樣式 sass文件路徑名。

 

3.  vux組件庫安裝後報錯:you may need an appropriate loader to handle this file type

即  三點 ...  這種沒有用 適當的 loader 來處理。這樣的錯誤,是由於使用了vux 2x版本,因此先要安裝 vux-loader 

  第一步:安裝:  npm install vux-loader --save-dev 

  第二步:配置:在 build ---> webpack.base.conf.js  裏修改。原來的 module.exports  使用 let originalConfig = xxx 來替換 。配置好後重啓項目就能使用了

修改前: 

...
module.exports = { ... }

修改後: 

...
let originalConfig  = { ... }

//下面的代碼放到最底部 const vuxLoader = require('vux-loader') module.exports = vuxLoader.merge(originalConfig , { plugins: ['vux-ui'] })

 

4.  import vux 組件,致使 棧溢出: Maximum call stack size exceeded

產生這個的緣由是: 引入的組件名 和當前 .vue文件中  export default 的name 值 相同,並且是 不區分大小寫的相同

修改方法: 把 name 值改爲其它不相同的便可。

 

5. 修改vux 組件庫某些組件的樣式。

第一種方法: 若是是修改組件中,提供的 樣式變量 這種官方提供的樣式修改。那麼,可使用下面的這種辦法:

  第一步: 在上面第三個安裝報錯問題處,修改爲如下代碼:

...
let originalConfig  = { ... }


//下面的代碼放到最底部
const vuxLoader = require('vux-loader')

module.exports = vuxLoader.merge(originalConfig , {
    plugins: ['vux-ui', 'progress-bar', 'duplicate-style', {name: 'less-theme', path: 'src/style/vux_theme.less'}]
})

  第二步: src下新建style文件夾,再新建vux_theme.less文件,而後裏面加入須要修改的樣式變量好比: @tabbar-text-active-color: #09BB07; 

  第三步:重啓項目便可。若是把樣式放到本身的 less 文件中,我發現仍是沒起做用。因此仍是乖乖的按照上面的步驟來弄。

第二種方法: 也是我的推薦的一種方式

  就是:在 style 中不使用 scoped 屬性。那麼這樣當前頁面的 樣式就至關於所有公用了。爲了防止樣式污染,那麼就須要在當前 .vue 組件中,最外層 div 加一個class 或者 id 值。這樣利用優先級去修改樣式便可。

第三種方式: 深度選擇器 /deep/ <<<

  你們都知道:若是使用了scoped屬性,那麼會在組件外層加上一個data-v的標識,致使修改不了組件內部的樣式,除非使用 /deep/ 或者 <<< 深度選擇器。可是深度選擇器不支持less,可是能夠轉換一種方法來寫就能夠支持:

@deep: ~'>>>'; 
.parent-custom { 
@{deep} .child-title { 
        font-size:20px;
        color: red; 
    } 
}

(1) 注意 深度選擇器 >>>  前面必定要加上  波浪符號 ~  。這樣表示不編譯後面的內容,所有以字符串輸出

(2) 這種深度選擇器,也能夠用於修改 v-html 的內容中的樣式。

 

6.  使用 px2rem 以後,不編譯第三方UI組件庫的px單位的方法:

  第一步: 不要安裝 px2rem-loader 。須要安裝 npm i postcss-px2rem-exclude –save  

  第二步: vue-cli搭建的環境中,有個.postcssrc.js文件,而後在這個文件修改爲以下的代碼:

module.exports = {
  "plugins": {
    "postcss-import": {},
    "postcss-url": {},
    // to edit target browsers: use "browserslist" field in package.json
    "autoprefixer": {},
  // 須要添加的內容
'postcss-px2rem-exclude': { remUnit: 75, exclude: /node_modules|folder_name/i // 忽略node_modules目錄下的文件 } } }

(1) 由於第三方 ui 庫的meta 都是   <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">  ,使用 flexible 以後會自動添加 meta,當meta 縮放是0.5的時候,就會縮小。

(2) remUnit 在這裏要根據 lib-flexible 的規則來配製,若是設計稿是750px的,用75就剛恰好。

(3) 若是不想 讓 px 編譯成 rem 。能夠在這個樣式後,加上/*no*/ 。例如  border:1px solid #ccc;/*no*/  

(4) 注意,px2rem 插件 不能讓 行內樣式 和 js動態加入的 px單位轉變成 rem。 若是實在要讓 js 中的px單位轉換成 rem,那麼,能夠用 設計稿中的 大小 來除以 remUnit 的大小,獲得的就是 正常的 rem值。好比,我 750px 設計圖上是 200的寬度,那麼 rem 就是 200 / 75 = 2.666666。最後再拼接'rem'成字符串便可。

在第二步中還有的說法是:在 package.json 中配置以下代碼:

"postcss": {
    "plugins": {
        "autoprefixer": {},
        "postcss-px2rem-exclude": {
            "remUnit": 75,
            "exclude": "/node_modules|folder_name/i"
        }
    }
}    

不過,配置事後並未起做用。因此建議仍是用前面的方法

 

7.  使用 lib-flexible 以後,在index.html中不要添加縮放的那個meta,插件會自動添加。不然會出現將 「將根據已有的meta標籤來設置縮放比例」 的警告。

 

8.  dcloud 5+ app 之分享功能。分享總共分三步(記住要先在 manifest.json 文件中的SDK配置中,把申請的分享的各類 appid、appkey等內容填寫好):

  第一步:是獲取分享服務列表,即 獲取 qq,新浪微博,微信。這三個分享服務

  第二步:判斷該服務是否受權。若是受權就進入分享的函數,不然去獲取受權

  第三步:在受權成功的狀況下,就進行分享。

完整的代碼以下:

html 部分
<div v-for="(i,idx) in list" :key="'share_'+idx" @click="judegeAuthorize(list[idx].id)"></div>

js 部分
data:function(){
  let curPath = (location.origin + location.pathname).replace('index.html',''); //由於是打包成app,因此沒有網絡路徑,若是要分享本地圖片,就必須用這種方式來拼接本地圖片的路徑。
  let imgPath = curPath + 'static/image/public/defaultHeader.png'; //分享的圖片的路徑
  return{
    shareLink:'http://www.baidu.com', //分享連接  list: [ { id:
"weixin", imgurl: "static/image/public/msg_share_weixin.png", title: "微信", ex:'WXSceneSession' }, { id: "weixinFriends", imgurl: "static/image/public/msg_share_friends.png", title: "朋友圈", ex:'WXSceneTimeline' }, { id: "qq", imgurl: "static/image/public/msg_share_qq.png", title: "QQ" }, { id: "sinaweibo", imgurl: "static/image/public/msg_share_weibo.png", title: "微博" }  ],  shareOptions:{}, //分享渠道:微信、QQ、新浪微博 //qq分享的內容選項 qqOptions:{ title:'這是QQ分享的標題', //(必填,最長30個字符) content:'這是QQ分享的內容', //(可選,最長40個字符) thumbs: [imgPath], // 數組類型 href:this.shareLink }, //微信分享的內容選項 weixinOptions:{ title:'這是微信好友分享的標題', content:'這是微信好友分享的內容', thumbs: [imgPath], href:this.shareLink, extra:{ scene:"WXSceneSession" } }, // 微信朋友圈分享的內容選項 weixinFriendsOptions:{ title:'這是微信朋友圈分享的標題', content:'這是微信朋友圈分享的內容', thumbs: [imgPath], href:this.shareLink, extra:{ scene:"WXSceneTimeline" } }, //新浪微博分享的內容選項 sinaweiboOptions:{ content:'這是新浪微博分享的內容', href:this.shareLink, pictures: [imgPath] } } }, created:function(){ var that = this; if(window.plus){ // 擴展API加載完畢,如今能夠正常調用擴展API plus.share.getServices(function(data){ var shareObj = {}; for(var i in data){ shareObj[ data[i].id ] = data[i]; } that.shareOptions = shareObj; }, function(){ plus.nativeUI.toast('獲取分享服務列表失敗') }) } }, methods:{ //處理分享功能 shareHandler:function(target,config){ target.send(config, function(msg){ plus.nativeUI.toast("分享到"+target.description+"成功"); },function(e){ console.log(e) let msg = e.code == -2 ? '已取消分享' : "分享到"+target.description+"失敗"; plus.nativeUI.toast(msg); }); }, //判斷是否受權 judegeAuthorize:function(id){ var target = this.shareOptions; if(JSON.stringify(target) == '{}'){ plus.nativeUI.toast("分享組件未準備好,請稍後再試"); return } let config = null; switch(id){ case 'weixin': config = this.weixinOptions; break; case 'weixinFriends': config = this.weixinFriendsOptions; id = 'weixin'; break; case 'qq': config = this.qqOptions; break; case 'sinaweibo': config = this.sinaweiboOptions; break; } var that = this; if(target[id].authenticated){ this.shareHandler(target[id],config); }else{ target[id].authorize( function(){ plus.nativeUI.toast("受權成功"); that.shareHandler(target[id],config); }, function(e){ plus.nativeUI.toast("受權失敗"); }); } } }

注意事項:

(1) 朋友圈和微信好友的區別就是 擴展內容 extra 裏的 scene 不一樣。

(2) 分享的圖片路徑,都是數組類型。

(3) 微信的分享,若是是直接返回,並無分享,可是結果返回也是分享成功。新浪微博獲取不了分享是否成功的狀態,不知道是否我哪裏弄錯了。若是qq分享失敗,查看參數是否正確,或者圖片是不是數組類型。

(4) 能夠不用官方的 document.addEventListener('plusready',function(){})  來判斷 plus是否準備好。能夠直接判斷 window.plus 來看plusready是否準備好。

 

9. 引入 mui.js 報錯

引入:在 main.js 中導入  import mui from './assets/js/mui.js'  。而後報錯了。 may not be accessed on strict mode

產生這樣的緣由是由於: vue-cli 使用了 babel 把es6 轉成es5 ,默認的是使用的嚴格模式。解決的辦法:在 .babelrc 文件中修改

  增長忽略babel編譯的文件:在與 plugins 同級的位置添加:  "ignore":["./src/assets/js/mui.min.js"]    後面的就是 mui.min.js 的文件位置 

而後就能夠 把 mui 掛在到 Vue 原型上了。

 

10.  設置沉浸式導航欄

if(window.plus){
      console.log('設置狀態欄')
      plus.navigator.setStatusBarBackground('#fff');//設置狀態欄背景顏色
      plus.navigator.setStatusBarStyle('light');//設置狀態欄字體顏色
}

(1) 狀態欄字體顏色 只支持 light 和 dark 兩個值。

(2) 若是在設置了 keep-alive 的組件頁面中,有可能前面的頁面會影響當前頁面。那麼能夠在 activated,deactivated 的 方法裏面再設置一次。

 

11.  打包成app以後,安卓後退鍵的處理。有兩種方式:

  第一種: 使用 5+ 監聽安卓後退按鈕。在vue的生命週期中調用

document.addEventListener('plusready', function() {
      var first = null;
      var webview = plus.webview.currentWebview();
      plus.key.addEventListener('backbutton', function() {
        webview.canBack(function(e) {
          if (e.canBack) {
            webview.back(); //這裏不建議修改本身跳轉的路徑
          } else {
            //首次按鍵,提示‘再按一次退出應用’
            if (!first) {
              first = new Date().getTime(); //獲取第一次點擊的時間戳
              plus.nativeUI.toast('再按一次退出應用', {
                duration: 'short'
              }); 
              setTimeout(function() {
                first = null;
              }, 1000);
            } else {
              if (new Date().getTime() - first < 1000) {
                //獲取第二次點擊的時間戳, 兩次之差 小於 1000ms 說明1s點擊了兩次,
                plus.runtime.quit(); //退出應用
              }
            }
          }
        })
      });
    })

(1) 這種不支持用 mui.openWindow 打開的頁面的返回。除非 再去判斷 是否有 指定ID 打開的webview  plus.webview.getWebviewById('自定義的頁面id')  。而後再去關閉指定ID的webview頁面。 plus.webview.close('jmyc') 

(2) 這種方式也有點問題,兩次的點擊時候須要小於1s才能後退。

  第二種: 引入 mui 。在vue的生命週期中調用:

data:{
    openWebView:false, //是否打開了頁面
},
created:function(){
  this.$mui.init({
      beforeback: function(){
        if(_this.openWebView){
          //得到列表界面的webview jmyc
          var viewObj = plus.webview.getWebviewById('jmyc');
          //canBack查詢窗口是否可退
           viewObj.canBack((event) => {
            var canBack = event.canBack;  
            if(canBack) {//如可退,則返回上一頁面
              viewObj.back();
            } else {//如不可退,則退出窗口
              plus.webview.close('jmyc')
              _this.openWebView = false;
            }
          })
          return false;
        }
        return true;
      }
   });  
}

(1) 前提是mui已經在 main.js 中引入,而且掛在到了vue 原型上 

import mui from './assets/js/mui.min.js'
Vue.prototype.$mui = mui

(2) 這種方式的好處就是,不用去判斷是否超過一秒。

 

12. 路由的懶加載,實現按需加載。

// 實現路由懶加載
function lazyLoad(filename){
  return () => import(`@/page/${filename}/index.vue`);
}

export default new Router({
  routes: [
    {
      path: '/index',
      name: 'indexToo',
      component: lazyLoad('index'),
      meta: {
        keepAlive: true // 須要被緩存
      },
    {
      path: '*',
      name: 'z_page404',  //404頁面 , 必須放在最底部
      component: lazyLoad('z_page404')
    }    
  ]
})

(1) 上面這種寫法,是由於 每一個 page 都新建了一個 index.vue 文件當作頁面,而後文件夾以不一樣的名稱來區分。

 

13.  須要緩存的頁面的處理:

第一步: 須要緩存的才使用 keep - alive 

<keep-alive>
    <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>

第二步: 在 router.js中配置 meta 

export default new Router({
  routes: [
    {
      path: '/index',
      name: 'index',
      component: lazyLoad('index'),
      meta: {
        keepAlive: true // 須要被緩存
      }    
  ]
})

若是想某些頁面動態來判斷是否緩存: 好比,當前頁面是 A ,須要緩存,可是從 B 頁面返回來以後,A頁面須要更新內容就不能緩存。在與 created 生命週期 同級上寫。

// 若是路由進入前,是從 B頁面返回來的,那麼就設置當前 A 頁面不緩存,不然緩存
  beforeRouteEnter(to, from, next) {
    if(from.path == '/B'){
      to.meta.keepAlive = false; 
    }else{
      to.meta.keepAlive = true;
    }
    next();
 },

(1) 最後必定要調用 next() 方法。

 

14. 打包成app 以後,圖片,css,js等路徑不正確

  若是沒有修改其它的路徑什麼的,多半是config文件夾中index.js裏面,buildassetsPublicPath路徑爲」 /」 是絕對路徑,把它改成相對路徑 「./」 就能夠了。而後從新打包

  項目中,不論是img標籤中的圖片,仍是 css中的背景圖片,都須要使用相對路徑

 

15.  若是想更方便的調試 5+ plus的效果:

  建議在 5+ app 的 index.html 添加一個 a標籤,href就是當前 項目運行的網絡路徑。 這樣只用在基座上運行一次,而後項目每次修改,均可以看到效果。

  若是是自定義基座,運行了以後,怕看不到控制檯的內容,hbuilderX 自帶有 webview 調試。運行以後,有個連接能夠點擊,就可使用谷歌的 inspect 來調試

  或者 使用 Vconsole 來調試

 

16. 斷網的處理

data:{
    networkStatus: false
},
created:function(){  
    let that = this;
    document.addEventListener("netchange", function () { //監聽網絡變化事件  
      // 延遲二秒獲取網絡狀態
      setTimeout( () => {
        let target = plus.networkinfo.getCurrentType();
        // 0 表示不認識的網絡。 1表示未鏈接網絡
        if ( target == 0 || target == 1) {  
          console.log('無網絡鏈接',target)
          that.networkStatus = true;
          that.$store.commit('changeNetworkStatus',true);
        }else{
          that.networkStatus = false;
          that.$store.commit('changeNetworkStatus',false);
        }
      },2000)        
    }, false);  
}

(1) 用了vuex存放了當前網絡狀態。通常把斷網的顯示內容封裝成一個組件,而後在這個組件裏寫入上面的內容。

(2) 而後在 APP.vue 中引入 組件。而後再根據 vuex中網絡的狀態,決定是否顯示斷網組件。

相關文章
相關標籤/搜索