VueJs项目笔记

======================知识点总结===========================

一、keep-alive(实现页面的缓存)

二、 移动端固定定位的解决方案

三、 Vue表单校验

  • [https://www.zhihu.com/questio...
  • 99220](https://www.zhihu.com/questio... "Vue表单验证")
  • https://github.com/aweiu/vue-verify-pop
  • vue-validator中文文档

    • https://github.com/kazupon/vu...

横向滑动的tab选项卡,以及输入法定位相关的

  • JQ插件网http://jq22.com
  • 当第一个输入框自动获得光标的时候,弹出的输入法会把布局顶上去

问题1:可以左右滑动的tab

  • 将项目中引入Jq框架和tab插件

当第一个输入框自动获得光标的时候,弹出的输入法会把布局顶上去?

  • 给最外层盒子加上绝对定位,并且设置固定高度

     .reg-layer {
       width: 100%;
       height: 360px;
       background: #ffffff;
       position: absolute;
       left: 0;
       top: 0;
       bottom: 0;
       right: 0;
     }
  • 再给登录框设置固定

     .login-main {
       width: 100%;
       height: 4rem;
       background-color: #ffffff;
       padding-top: 0.4rem;
     }
    

怎么去加载一倍图,二倍图,三倍图等

  • 使用Retina.js

上拉刷新、下拉加载更多

  • VUe-Scroller

    • https://github.com/wangdahoo/...

登录注册

  • VueJs保存token
  • 判断token失效

VueJs保存token

  • http://blog.csdn.net/generon/...
  • https://segmentfault.com/q/10...
  • http://www.jb51.net/article/1...
  • http://shequ.jb51.net/q_1599....

Vue-cli proxyTable 解决开发环境的跨域问题

  • http://blog.csdn.net/hsany330...
  • https://segmentfault.com/q/10...

使用localStorage解决vuex在页面刷新后数据被清除的问题

  • http://www.cnblogs.com/limeng...

如何在vue中实现路由跳转判断用户权限功能?

  • https://segmentfault.com/q/10...

Axios

  • http://www.cnblogs.com/libin-...

Ju Network Status By JS

  • https://github.com/HubSpot/of...
  • https://segmentfault.com/a/11...
  • https://segmentfault.com/q/10...
  • http://wicg.github.io/netinfo/

Web App Notes

  • http://blog.csdn.net/zhangxin...

Axios WebSite Address

  • http://www.kancloud.cn/yunye/...

No NetWork SPA

  • https://github.com/NekR/offli...

VueJS Communication among brothers

  • http://www.cnblogs.com/zsongs...

webpack多页应用架构系列

  • https://segmentfault.com/a/11...

Vue-Cli配置文件分析

  • http://blog.csdn.net/hongchh/...
  • http://blog.csdn.net/s8460049...

下拉刷新

  • 获取VueScroller实例:this.$refs.my_scroller
  • 显示没有更多数据了,在那个infinate()方法中调用done(true)就OK了
  • http://www.cnblogs.com/liangx...
  • http://m.codes51.com/article/...

Vue-Cli打包发布

  • http://www.cnblogs.com/libin-...
  • http://www.tuicool.com/articl...

移动端-webkit-user-select:none导致input/textarea输入框无法输入

  • http://www.qdfuns.com/notes/1...
  • http://www.jianshu.com/p/4108...

VueJs判断Token过期

  • http://www.tuicool.com/articl...

Axios中的delete请求

  • https://github.com/pagekit/vu...

VueJs移动端图片压缩上传

  • https://my.oschina.net/myrain...
  • 图片压缩插件

    • https://github.com/think2011/...

React Note

  • http://www.runoob.com/react/r...

Refresh Current Page

_this.$router.go(0);

How I can config https in Vue-Cli

  • https://segmentfault.com/q/10...

use Vue-Scroller

    {
    test: /vue-scroller.src.*?js$/,
    loader: 'babel-loader'
  }
  • It can invoked inflate() method automatically when vue component is mounted,there is a way to solve this problem

    this.$refs.my_scroller.finishInfinite(true);

Wechat share in VueJs Projects

  • http://www.cnblogs.com/mingxi...
  • https://segmentfault.com/q/10...

微信公众号

  • https://mp.weixin.qq.com/cgi-...

UpLoad File In VueJs

  • https://github.com/marchFanta...
  • https://github.com/lian-yue/v...
  • https://github.com/mozilla/pd...

Show PDF In Broswer

  • Using Pdf.js
  • https://segmentfault.com/q/10...
  • https://github.com/mozilla/pd...
  • https://stackoverflow.com/que...

Show PDF In Broswer Code

  • http://localhost:63342/pdf.js-gh-pages/examples/index.html?_ijt=s4h3uipnnk8bec8b1ddn82mqnn
  • it must be contain a canvas tag

    import PDFJS from 'pdfjs-dist';
    showPDF(){
            let pdfPath = '/static/compressed.tracemonkey-pldi-09.pdf';
            let  loadingTask = PDFJS.getDocument(pdfPath);
            loadingTask.promise.then(function (pdfDocument) {
              // Request a first page
              return pdfDocument.getPage(1).then(function (pdfPage) {
                console.log("pdfPage is :",pdfPage);
                // Display page on the existing canvas with 100% scale.
                let scale = 1.5;    
                let viewport = pdfPage.getViewport(scale);
                let canvas = document.getElementsByClassName('theCanvas');
                canvas.width = viewport.width;
                canvas.height = viewport.height;
                let ctx = canvas.getContext('2d');
                let renderTask = pdfPage.render({
                  canvasContext: ctx,
                  viewport: viewport
                });
                return renderTask.promise;
              });
            }).catch(function (reason) {
              console.error('Error: ' + reason);
            });
          },
    

DownLoad files

  • https://www.npmjs.com/package...

PDF.js怎么一次性的加载完所有的pdf的内容

在进行文件(pdf、word)等的上传中,怎么区分?

  • http://blog.csdn.net/shenshen...
  • article/details/21626315
  • accept="application/msexcel" ----对应上传excel
  • accept="application/msword" ----对应上传word
  • accept="application/pdf" ----对应上传pdf

PDF.js Example

  • https://github.com/mozilla/pd...

PDF.js Frequently Asked Questions

  • https://github.com/mozilla/pd...

PDFViewer.vue




viewer.js

/* Copyright 2016 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/* globals PDFJS */

'use strict';

if (!PDFJS.PDFViewer || !PDFJS.getDocument) {
  alert('Please build the pdfjs-dist library using\n' +
        '  `gulp dist-install`');
}

PDFJS.useOnlyCssZoom = true;
PDFJS.disableTextLayer = true;
PDFJS.maxImageSize = 1024 * 1024;
PDFJS.workerSrc = '../../../node_modules/pdfjs-dist/build/pdf.worker.js';
PDFJS.cMapUrl = '../../../node_modules/pdfjs-dist/cmaps/';
PDFJS.cMapPacked = true;
//需要加载的pdf的文件
// var DEFAULT_URL = 'https://cdn.rawgit.com/mozilla/pdf.js/c6e8ca86/test/pdfs/calrgb.pdf';
// var DEFAULT_URL = 'http://192.168.0.200:8080/media/avatar/fluent-python.pdf';
var DEFAULT_SCALE_DELTA = 1.0;
var MIN_SCALE = 0.25;
var MAX_SCALE = 100.0;
var DEFAULT_SCALE_VALUE = 'auto';

var PDFViewerApplication = {
  pdfLoadingTask: null,
  pdfDocument: null,
  pdfViewer: null,
  pdfHistory: null,
  pdfLinkService: null,

  /**
   * Opens PDF document specified by URL.
   * @returns {Promise} - Returns the promise, which is resolved when document
   *                      is opened.
   */
  open: function (params) {
    if (this.pdfLoadingTask) {
      // We need to destroy already opened document
      return this.close().then(function () {
        // ... and repeat the open() call.
        return this.open(params);
      }.bind(this));
    }

    var url = params.url;
    var self = this;
    this.setTitleUsingUrl(url);

    // Loading document.
    var loadingTask = PDFJS.getDocument(url);
    this.pdfLoadingTask = loadingTask;

    loadingTask.onProgress = function (progressData) {
      self.progress(progressData.loaded / progressData.total);
    };

    return loadingTask.promise.then(function (pdfDocument) {
      // Document loaded, specifying document for the viewer.
      self.pdfDocument = pdfDocument;
      self.pdfViewer.setDocument(pdfDocument);
      self.pdfLinkService.setDocument(pdfDocument);
      self.pdfHistory.initialize(pdfDocument.fingerprint);
      self.loadingBar.hide();
      self.setTitleUsingMetadata(pdfDocument);
    }, function (exception) {
      var message = exception && exception.message;
      var l10n = self.l10n;
      var loadingErrorMessage;

      if (exception instanceof PDFJS.InvalidPDFException) {
        // change error message also for other builds
        loadingErrorMessage = l10n.get('invalid_file_error', null,
          'Invalid or corrupted PDF file.');
      } else if (exception instanceof PDFJS.MissingPDFException) {
        // special message for missing PDFs
        loadingErrorMessage = l10n.get('missing_file_error', null,
          'Missing PDF file.');
      } else if (exception instanceof PDFJS.UnexpectedResponseException) {
        loadingErrorMessage = l10n.get('unexpected_response_error', null,
          'Unexpected server response.');
      } else {
        loadingErrorMessage = l10n.get('loading_error', null,
          'An error occurred while loading the PDF.');
      }

      loadingErrorMessage.then(function (msg) {
        self.error(msg, {message: message});
      });
      self.loadingBar.hide();
    });
  },

  /**
   * Closes opened PDF document.
   * @returns {Promise} - Returns the promise, which is resolved when all
   *                      destruction is completed.
   */
  close: function () {
    var errorWrapper = document.getElementById('errorWrapper');
    errorWrapper.setAttribute('hidden', 'true');

    if (!this.pdfLoadingTask) {
      return Promise.resolve();
    }

    var promise = this.pdfLoadingTask.destroy();
    this.pdfLoadingTask = null;

    if (this.pdfDocument) {
      this.pdfDocument = null;

      this.pdfViewer.setDocument(null);
      this.pdfLinkService.setDocument(null, null);
    }

    return promise;
  },

  get loadingBar() {
    var bar = new PDFJS.ProgressBar('#loadingBar', {});

    return PDFJS.shadow(this, 'loadingBar', bar);
  },

  setTitleUsingUrl: function pdfViewSetTitleUsingUrl(url) {
    this.url = url;
    var title = PDFJS.getFilenameFromUrl(url) || url;
    try {
      title = decodeURIComponent(title);
    } catch (e) {
      // decodeURIComponent may throw URIError,
      // fall back to using the unprocessed url in that case
    }
    this.setTitle(title);
  },

  setTitleUsingMetadata: function (pdfDocument) {
    var self = this;
    pdfDocument.getMetadata().then(function(data) {
      var info = data.info, metadata = data.metadata;
      self.documentInfo = info;
      self.metadata = metadata;

      // Provides some basic debug information
      console.log('PDF ' + pdfDocument.fingerprint + ' [' +
                  info.PDFFormatVersion + ' ' + (info.Producer || '-').trim() +
                  ' / ' + (info.Creator || '-').trim() + ']' +
                  ' (PDF.js: ' + (PDFJS.version || '-') +
                  (!PDFJS.disableWebGL ? ' [WebGL]' : '') + ')');

      var pdfTitle;
      if (metadata && metadata.has('dc:title')) {
        var title = metadata.get('dc:title');
        // Ghostscript sometimes returns 'Untitled', so prevent setting the
        // title to 'Untitled.
        if (title !== 'Untitled') {
          pdfTitle = title;
        }
      }

      if (!pdfTitle && info && info['Title']) {
        pdfTitle = info['Title'];
      }

      if (pdfTitle) {
        self.setTitle(pdfTitle + ' - ' + document.title);
      }
    });
  },
  /**
   * 设置title标题
   * @param title
   */
  setTitle: function pdfViewSetTitle(title) {
    document.title = title;
    console.log("document.title:",document.title,document,document.getElementById('title').textContent);
    if(document.getElementById('title').textContent!==''){
      document.getElementById('title').textContent = title;
    }
  },

  error: function pdfViewError(message, moreInfo) {
    var l10n = this.l10n;
    var moreInfoText = [l10n.get('error_version_info',
      {version: PDFJS.version || '?', build: PDFJS.build || '?'},
      'PDF.js v{{version}} (build: {{build}})')];

    if (moreInfo) {
      moreInfoText.push(
        l10n.get('error_message', {message: moreInfo.message},
          'Message: {{message}}'));
      if (moreInfo.stack) {
        moreInfoText.push(
          l10n.get('error_stack', {stack: moreInfo.stack},
            'Stack: {{stack}}'));
      } else {
        if (moreInfo.filename) {
          moreInfoText.push(
            l10n.get('error_file', {file: moreInfo.filename},
              'File: {{file}}'));
        }
        if (moreInfo.lineNumber) {
          moreInfoText.push(
            l10n.get('error_line', {line: moreInfo.lineNumber},
              'Line: {{line}}'));
        }
      }
    }

    var errorWrapper = document.getElementById('errorWrapper');
    errorWrapper.removeAttribute('hidden');

    var errorMessage = document.getElementById('errorMessage');
    errorMessage.textContent = message;

    var closeButton = document.getElementById('errorClose');
    closeButton.onclick = function() {
      errorWrapper.setAttribute('hidden', 'true');
    };

    var errorMoreInfo = document.getElementById('errorMoreInfo');
    var moreInfoButton = document.getElementById('errorShowMore');
    var lessInfoButton = document.getElementById('errorShowLess');
    moreInfoButton.onclick = function() {
      errorMoreInfo.removeAttribute('hidden');
      moreInfoButton.setAttribute('hidden', 'true');
      lessInfoButton.removeAttribute('hidden');
      errorMoreInfo.style.height = errorMoreInfo.scrollHeight + 'px';
    };
    lessInfoButton.onclick = function() {
      errorMoreInfo.setAttribute('hidden', 'true');
      moreInfoButton.removeAttribute('hidden');
      lessInfoButton.setAttribute('hidden', 'true');
    };
    moreInfoButton.removeAttribute('hidden');
    lessInfoButton.setAttribute('hidden', 'true');
    Promise.all(moreInfoText).then(function (parts) {
      errorMoreInfo.value = parts.join('\n');
    });
  },

  progress: function pdfViewProgress(level) {
    var percent = Math.round(level * 100);
    // Updating the bar if value increases.
    if (percent > this.loadingBar.percent || isNaN(percent)) {
      this.loadingBar.percent = percent;
    }
  },

  get pagesCount() {
    return this.pdfDocument.numPages;
  },

  set page(val) {
    this.pdfViewer.currentPageNumber = val;
  },

  get page() {
    return this.pdfViewer.currentPageNumber;
  },

  zoomIn: function pdfViewZoomIn(ticks) {
    var newScale = this.pdfViewer.currentScale;
    do {
      newScale = (newScale * DEFAULT_SCALE_DELTA).toFixed(2);
      newScale = Math.ceil(newScale * 10) / 10;
      newScale = Math.min(MAX_SCALE, newScale);
    } while (--ticks && newScale < MAX_SCALE);
    this.pdfViewer.currentScaleValue = newScale;
  },

  zoomOut: function pdfViewZoomOut(ticks) {
    var newScale = this.pdfViewer.currentScale;
    do {
      newScale = (newScale / DEFAULT_SCALE_DELTA).toFixed(2);
      newScale = Math.floor(newScale * 10) / 10;
      newScale = Math.max(MIN_SCALE, newScale);
    } while (--ticks && newScale > MIN_SCALE);
    this.pdfViewer.currentScaleValue = newScale;
  },

  initUI: function pdfViewInitUI() {
    var linkService = new PDFJS.PDFLinkService();
    this.pdfLinkService = linkService;

    this.l10n = PDFJS.NullL10n;

    var container = document.getElementById('viewerContainer');
    var pdfViewer = new PDFJS.PDFViewer({
      container: container,
      linkService: linkService,
      l10n: this.l10n,
    });
    this.pdfViewer = pdfViewer;
    linkService.setViewer(pdfViewer);

    this.pdfHistory = new PDFJS.PDFHistory({
      linkService: linkService
    });
    linkService.setHistory(this.pdfHistory);

    document.getElementById('previous').addEventListener('click', function() {
      PDFViewerApplication.page--;
    });

    document.getElementById('next').addEventListener('click', function() {
      PDFViewerApplication.page++;
    });

    document.getElementById('zoomIn').addEventListener('click', function() {
      PDFViewerApplication.zoomIn();
    });

    document.getElementById('zoomOut').addEventListener('click', function() {
      PDFViewerApplication.zoomOut();
    });

    document.getElementById('pageNumber').addEventListener('click', function() {
      this.select();
    });

    document.getElementById('pageNumber').addEventListener('change',
        function() {
      PDFViewerApplication.page = (this.value | 0);

      // Ensure that the page number input displays the correct value, even if the
      // value entered by the user was invalid (e.g. a floating point number).
      if (this.value !== PDFViewerApplication.page.toString()) {
        this.value = PDFViewerApplication.page;
      }
    });

    container.addEventListener('pagesinit', function () {
      // We can use pdfViewer now, e.g. let's change default scale.
      pdfViewer.currentScaleValue = DEFAULT_SCALE_VALUE;
    });

    container.addEventListener('pagechange', function (evt) {
      var page = evt.pageNumber;
      var numPages = PDFViewerApplication.pagesCount;

      document.getElementById('pageNumber').value = page;
      document.getElementById('previous').disabled = (page <= 1);
      document.getElementById('next').disabled = (page >= numPages);
    }, true);
  }
};

document.addEventListener('DOMContentLoaded', function () {
  PDFViewerApplication.initUI();
}, true);

(function animationStartedClosure() {
  // The offsetParent is not set until the PDF.js iframe or object is visible.
  // Waiting for first animation.
  PDFViewerApplication.animationStartedPromise = new Promise(
    function (resolve) {
      window.requestAnimationFrame(resolve);
    });
})();

/*// We need to delay opening until all HTML is loaded.
PDFViewerApplication.animationStartedPromise.then(function () {
  PDFViewerApplication.open({
    url: DEFAULT_URL
  });
});*/
export default PDFViewerApplication;

VueJs防止页面出现闪烁的情况

  • v-cloak指令

    • http://cn.vuejs.org/v2/api/#v...

处理TextArea自动随文本高度自适应高度

  • https://github.com/jackmoore/...

PC端与移动端中option的宽度问题

搜索布局的问题----子组件去解决

  • 路由切换(tab切换)实现不同的布局

VueJs NextTick的妙用

  • https://segmentfault.com/a/11...

回到原来的滚动位置以及回到顶部(待完善)

  • 当路处于离开状态的时候,存储滚动的位置
  • 当路由处于进入状态的时候,取出滚动位置进行判断,来显示或隐藏“返回顶部”的按钮

VueJs自动化测试

  • https://segmentfault.com/a/11...
  • https://github.com/ccforward/...

Web App中一行文字显示不下,左边用...表示

  • https://segmentfault.com/q/10...

刷新当前页面

  • this.$router.go(0);

VueJs打包优化

  • https://www.zhihu.com/questio...

WebPack中静态资源url的配置

  • http://www.cnblogs.com/chengd...

Vue-Cli webpack配置

  • http://www.tuicool.com/articl...

移动端富文本框的集成

  • https://quilljs.com/playground/
  • vue-html5-editor

Vue-Router中push与replace的区别与联系

  • https://segmentfault.com/q/10...

VueJs富文本框(发帖功能)

  • 移动端:https://github.com/surmon-chi...
  • https://github.com/PeakTai/vu...

div设置了contentEditable属性。android上正常,IOS上出现问题

  • 使用div来模拟input或者textarea来进行内容输入的操作,实现富文本框的功能
  • 遇到问题

    加入style="-webkit-user-select: auto"就能出现光标和编辑了

Vuejs-Cordova-Framework-Webapp

  • http://blog.gxxsite.com/vuejs...
  • vue-cordova

Css-Scroller(效果图,暂时不用在项目中)

  • https://github.com/xiaoluobod...

Scroll开源库实现列表滚动动画

  • https://github.com/hakimel/st...

H5控制禁止横屏

  • http://www.jianshu.com/p/9c32...

文件上传(do not)

  • https://github.com/marchFanta...

window.open被拦截问题(完成)

  • 通过借用a标签并产生随机的target去实现

`

                s4() {
                  return Math.floor((1 + Math.random()) * 0x10000)
                  .toString(16)
                  .substring(1);
                },
                JsGuid() {
                return this.s4() + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' +
                  this.s4() + '-' + this.s4() + this.s4() + this.s4();
                },
        
                 newWin(url, id,target) {
                  let a = document.createElement('a');
                  a.setAttribute('href', url);
                  a.setAttribute('target', target);
                  a.setAttribute('id', id);
                  // 防止反复添加
                  if(!document.getElementById(id)) {
                    document.body.appendChild(a);
                  }
                  a.click();
                },

`

  • 调用

    this.newWin(localStorage.getItem('url'),"dow","csa"+this.JsGuid());

log工具类(便于在开发过程中进行调试打印),在上线后将所有log信息隐藏

  • code

    /**

    • Created by THINK on 2017/7/3.
    • 日志工具类:开发阶段将flag设置为true(可以看见log),上线后将flag设置为false(看不见log)
    • @author:darkCode
    • @description:it is a logcat tool,you can use it see all logs you want to see conveniently when developing,and you can hide all logs by set the value of flag is false in this instance when producting
             */
            let logUtil = {
              flag:true,
              printLog(...items){
                if(this.flag){
                  console.log(items);
                }
              }
            }
            export default logUtil

修复上拉刷新,下拉加载

  • vue-scroller(自动地去进行了加载更多(bug))

对项目进行优化性的操作

  • 代码复用
  • 资源的处理

安卓模拟器测试

  • 安装问题:进入Bios系统设置硬件虚拟化

虚拟化技术的可以在BIOS中开启,开启方法如下:

  1、进入BIOS。开机时按F2或F12或DEL或ESC等键(各电脑有所不同)。
  2、进入BIOS后,找到Configuration选项,选择Intel Virtual Technology并回车,将光标移至Enabled,然后再回车,最后按F10保存并退出。
  如果找不到Configuration选项,可以试试下面的方法:
  (1)某些HP(惠普)电脑进入BIOS后,需要选择SystemConfiguration(系统配置)菜单,然后选择Device Configuration(设备配置),找到Virtualization Technology,设置为Enabled。
  (2)某些联想Thinkpad电脑进入BIOS后,需要选择Security菜单,然后选择Virtualization,设置为Enabled。
  (3)某些DELL(戴尔)电脑进入BIOS后,需要选择Processor Settings菜单,然后选择VirtualizationTechnology,设置为Enabled。
  虚拟化在1960年为了描述虚拟机(实验性的IBM M44/44X系统)这个概念被第一次提出。对虚拟机的架设和管理被称为平台虚拟化,现在也被称为服务器虚拟化。

将业务逻辑代码与三方代码分开进行打包

  • 在entry入口中配置,如分离jQuery
  • 使用vue-cli打包后默认生产三个js文件

    • app.43fcdsfcafds.js:项目中你编写的业务逻辑的代码
    • vender.20deewdew32eed.js:通过npm install下载依赖的js,css代码(node_modules目录下)
    • manifest.4cbcd0f5d52237fb29b0.js:缓存检测文件,每次打包,通过该文件进行版本的检测
  • 将生产环境与开发环境中的资源打包使用

vender:3.34m app:1.26m,怎么去减少它们的体积

  • vender.xsaxsxx.js.map文件的作用

source map文件是js文件压缩后,文件的变量名替换对应、变量所在位置等元信息数据文件,一般这种文件和min.js主文件放在同一个目录下。 比如压缩后原变量是map,压缩后通过变量替换规则可能会被替换成a,这时source map文件会记录下这个mapping的信息,这样的好处就是说,在调试的时候,如果有一些JS报错,那么浏览器会通过解析这个map文件来重新merge压缩后的js,使开发者可以用未压缩前的代码来调试,这样会给我们带来很大的方便!

文件的按需加载(搞定)---项目优化的一大步

  • 根据vue的路由去按需加载组件

    • http://www.cnblogs.com/Nutrie...
  • vue组件的按需加载:解决了打包过后app.xscs3243rcds.js文件过大的缺点
  • 进一步优化(三方不太动的js文件,通过cdn去加载)
  • 引用相同的模块,打包后出现重复的资源,将三方的单独进行打包

WebPack代码分割

  • https://zhuanlan.zhihu.com/p/...

WebPack中文网

  • https://doc.webpack-china.org...

VueJs Seo(Nuxt.js)

  • https://segmentfault.com/a/11...
  • https://segmentfault.com/q/10...

WeChat微信分享

  • http://blog.csdn.net/rj0902/a...
  • http://blog.csdn.net/kexiuyi/...
  • http://blog.csdn.net/u0132921...
  • http://www.jb51.net/article/1...
  • http://www.cnblogs.com/mingxi... cool)
  • 微信网页授权

    • https://mp.weixin.qq.com/wiki...

Vue-Cli中引入weixin-js-sdk

  • https://www.npmjs.com/package...
  • 苹果手机上设置分享的title的问题

    • https://www.deboy.cn/set-wech...
  • 微信分享

    • https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
  • 问题1:判断是否是微信浏览器打开应用,是,需要动态去设置帖子详情页的分享界面
     isWeiXin(){
        //判断是否是微信浏览器
        let ua = window.navigator.userAgent.toLowerCase();
        if (ua.match(/MicroMessenger/i) === 'micromessenger') {
          return true;
        } else {
          return false;
        }
      },
  • 分享实现流程

    • ①安装微信sdk npm install weixin-js-sdk --save-dev
    • ②通过import或者require的方式将其引入到需要的组件中
    • ③获取签名相关的信息
    • ④通过config接口注入权限验证配置

       wx.config({
      debug: true, 
      appId: '', // 必填,公众号的唯一标识
      timestamp: , // 必填,生成签名的时间戳
      nonceStr: '', // 必填,生成签名的随机串
      signature: '',// 必填,签名,见附录1
      jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
      });
      
    • ⑤通过ready接口处理成功验证

          wx.ready(function(){
      // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
              //进行分享的操作
               //分享到朋友圈
                wx.onMenuShareTimeline({
                  title: '测试信息', // 分享标题
                  link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                  imgUrl: '', // 分享图标
                  success: function (res) {
                    // 用户确认分享后执行的回调函数
                    logUtil.printLog("分享到朋友圈成功返回的信息为:",res);
                  },
                  cancel: function (res) {
                    // 用户取消分享后执行的回调函数
                    logUtil.printLog("取消分享到朋友圈返回的信息为:",res);
                  }
                });
                //分享给朋友
                wx.onMenuShareAppMessage({
                  title: '', // 分享标题
                  desc: '', // 分享描述
                  link: '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
                  imgUrl: '', // 分享图标
                  type: '', // 分享类型,music、video或link,不填默认为link
                  dataUrl: '', // 如果type是music或video,则要提供数据链接,默认为空
                  success: function (res) {
                    // 用户确认分享后执行的回调函数
                    logUtil.printLog("分享给朋友成功返回的信息为:",res);
                  },
                  cancel: function (res) {
                    // 用户取消分享后执行的回调函数
                    logUtil.printLog("取消分享给朋友返回的信息为:",res);
                  }
                });
                //分享到QQ
                wx.onMenuShareQQ({
                  title: '', // 分享标题
                  desc: '', // 分享描述
                  link: '', // 分享链接
                  imgUrl: '', // 分享图标
                  success: function (res) {
                    // 用户确认分享后执行的回调函数
                    logUtil.printLog("分享到QQ好友成功返回的信息为:",res);
                  },
                  cancel: function (res) {
                    // 用户取消分享后执行的回调函数
                    logUtil.printLog("取消分享给QQ好友返回的信息为:",res);
                  }
                });
                //分享到QQ空间
                wx.onMenuShareQZone({
                  title: '', // 分享标题
                  desc: '', // 分享描述
                  link: '', // 分享链接
                  imgUrl: '', // 分享图标
                  success: function (res) {
                    // 用户确认分享后执行的回调函数
                    logUtil.printLog("分享到QQ空间成功返回的信息为:",res);
                  },
                  cancel: function (res) {
                    // 用户取消分享后执行的回调函数
                    logUtil.printLog("取消分享到QQ空间返回的信息为:",res);
                  }
                });
      });
      
    • ⑥通过error接口处理失败验证

      • wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});    
  • 签名由:noncestr(签名随机字符串,随便写)、jsapi_ticket(票据)、timestamp(时间戳)、url(必须全部小写)等组成
  • 获取access_token

    请求接口:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=你的appid&secret=你的secret
    请求方法: get
    返回结果: access_token (有效期7200秒,必须在服务端缓存) 
  • 获取票据jsapi_ticket

    请求接口:https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=上一步中获取的access_token&type=jsapi
    请求方法: get,
    type: JSON,
    返回结果: jsapi_ticket (有效期7200秒,必须在服务端缓存)
  • 生成时间戳(timestamp)

    // 时间戳产生函数
    var timeStamp = function () {
        return parseInt(new Date().getTime() / 1000) + '';
    };
    
  • 签名算法(可以参考官方给出的demo:https://github.com/arronf2e/j...)

比如:

        var calcSignature =function(ticket,nonceStr,timeStamp,url) {
            var result = {
                jsapi_ticket: ticket,
                nonceStr: nonceStr,
                timestamp: timeStamp,
                url: url,
            }
            var str = 'jsapi_ticket=' + ticket + '&noncestr=' + nonceStr + '×tamp=' + timeStamp + '&url=' + url;
            // 对str使用sha1签名,得到signature,这里使用jsSHA模块,需install
            shaObj = new jsSHA(str, 'TEXT');
            result.signature = shaObj.getHash('SHA-1', 'HEX');
            return result; // 返回到前端,提供接口由前端请求
        }
  • 接下来就返回给前端使用(在获取签名的时候需要传递url:用于签名的(需要四个参数来实现签名:时间戳、ticket、前端传递的动态的url、nonceStr) url(动态的)给后端)]

微信分享

  • 微信分享问题总结:

    • http://blog.csdn.net/u011743396/article/details/62427452
  • ngork

    • https://www.zhihu.com/question/25456655
  • 问题描述

    • 微信 jssdk 需要签名,签名的 URL 和将要分享的 URL 必须要一致才会签名通过
    • url必须是当前网页的url不包含#及其后面部分(http://blog.sina.com.cn/s/blo...
  • ip地址查询:http://site.ip138.com
  • python sha1签名

    • http://blog.csdn.net/u014368609/article/details/50679818
  • js获取当前时间、时间戳

    • http://www.cnblogs.com/Man-Dream-Necessary/p/6369469.html
  • Vue路由按需加载

    • http://www.jb51.net/article/1...
  • 注意事项

    • 需要在配置文件webpack.base.conf.js中加入

      output:{
          pathinfo: true
      }
      
  • Vue服务端渲染

    • http://www.cnblogs.com/wangsh...
  • 后台管理

    • https://github.com/almasaeed2...

Axios下的接口封装

  • get操作,如:
import axios from 'axios';
        /**
         * 获取积分信息
         * @param url
         * @returns {*}
         */
        export function getJiFenDetailInfo(url) {
          return axios.get(url).then((res)=>{
            return Promise.resolve(res);
          },(err)=>{
            return Promise.reject(err);
          });
        }
  • post操作,如:
 import axios from 'axios';
        /**
         * 处理登录
         * @param url
         * @param mobile
         * @param password
         * @returns {*}
         */
        export function dealLogin(url,mobile,password) {
          return axios.post(url,{
            mobile:mobile,
            password:password
          }).then((res)=>{
            return Promise.resolve(res);
          },(err)=>{
            return Promise.reject(err);
          });
        }

基于VueJs的后台管理

  • https://github.com/PanJiaChen...
  • https://github.com/vue-bulma/...
  • https://github.com/taylorchen...

移动端html2canvas生成图片转换为File对象兼容处理

涉及点:Base64转换为file对象

 /**
       * 将Base64转换为file对象
       * @param dataurl:文件的base64表示
       * @param filename:文件名
       * @return {File}:返回的file对象
       */
      dataURLtoFile(dataurl, filename) {
        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
        while(n--){
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new File([u8arr], filename, {type:mime});
      },

发现ios低版本出现了兼容问题,最终发现问题出在new File()这里。那么就得想其他解决办法了,可以先将Base64进行二进制转换操作,最终将二进制转换为File对象就可以解决。

 /**
       * 将base64先转换为二进制对象
       * */
      dataURLtoBlob(dataurl) {
        var arr = dataurl.split(','),
          mime = arr[0].match(/:(.*?);/)[1],
          bstr = atob(arr[1]),
          n = bstr.length,
          u8arr = new Uint8Array(n);
        while (n--) {
          u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type: mime });
      },
      /**
       * 最后再将二进制转换为file对象
       * */
      blobToFile(theBlob, fileName){
        theBlob.lastModifiedDate = new Date();
        theBlob.name = fileName;
        return theBlob;
      },

it is done!

你可能感兴趣的:(webpack,运维,移动开发,ViewUI)