【vue】常見開發知識點與問題整理(持續更新)

1.vue雙向數據綁定vuex中的state

在vue中, 不容許直接綁定vuex的值到組件中, 如果直接使用, 則會報錯 have no setterjavascript

方法一: 使用get和sethtml

// 在從組件的computed中
computed: {
    user: {
        get() {
          return this.$store.state.user }, set(v) { // 使用vuex中的mutations中定義好的方法來改變 this.$store.commit('USER', v) } } } // 在組件中就可使用 <input v-modle="user" />

方法二: 使用watch前端

// 在組件中綁定
<input v-modle="user" />

// 在computed中獲取vuex的值
computed: {
  ...mapState( { user: state => state.user } ) } // 在組件的watch中觀測 watch: { 'user': { deep: true, handler(value) { // 使用vuex中的mutations中定義好的方法來改變 this.$store.commit('USER', value) } } }

 2.(webpack)vue-cli構建的項目如何設置每一個頁面的title

在路由裏每一個都添加一個meta:vue

[{
    path:'/login', meta: { title: '登陸頁面' }, component:'login' }]

鉤子函數,在main.js中添加以下代碼:html5

router.beforeEach((to, from, next) => {
  window.document.title = to.meta.title; next() })

3.vue項目中使用axios上傳圖片等文件

經過form表單提交,html代碼以下:java

<input name="file" type="file" accept="image/png,image/gif,image/jpeg" @change="update"/>

JS代碼:react

import axios from 'axios'

update(e) {
    let file = e.target.files[0] let param = new FormData(); // 建立form對象 param.append('file', file); // 經過append向form對象添加數據 param.append('chunk', '0'); // 添加form表單中其餘數據 let config = { // 添加請求頭  headers: { 'Content-Type': 'multipart/form-data' } }; axios.post('http://172.19.26.60:8080/user/headurl', param, config) .then(response => { if (response.data.code === 200) { this.ImgUrl = response.data.data; } }) }

 4.qs.stringify() 和JSON.stringify()的區別、vux中使用post提交表單數據須要qs庫序列化

qs庫的npm地址:https://www.npmjs.com/package/qswebpack

功能雖然都是序列化。假設我要提交的數據以下:ios

var a = {name:'hehe',age:10};

qs.stringify序列化結果以下:name=hehe&age=10git

而JSON.stringify序列化結果以下:"{"a":"hehe","age":10}"

vux中使用post提交表單數據:

this.$http.post(this.$sign.config.url.loginUrl,this.$qs.stringify({
    "phone":this.phoneNumber, "vCode":this.loginCode, "smsCode":this.phoneCode }) ) .then(response=>{ console.log(response.data); if(response.data.httpCode == 200){ }else{ } }) 

在firebug中能夠看到傳遞的參數:phone=15210275239&vCode=8vsd&smsCode=1534

在vue中使用axios:

this.$axios.post(loginUrl, {
    "email": this.email, "password": this.password }, { transformRequest: (data) => { return this.$qs.stringify(data) }, }).then(res => { if(res.data.resultCode == RESULT_CODE_SUCCESS){ console.log('登陸成功'); this.$router.push({name:"home"}) }else{ console.log('登陸失敗'); } }).catch(err => { console.log('登登陸出現錯誤'); })

 5.vue全局實現的setCookie、getCookie、delCookie

//設置cookie,增長到vue實例方便全局調用
Vue.prototype.setCookie = (c_name, value, expiredays) => {
  var exdate = new Date();     exdate.setDate(exdate.getDate() + expiredays);     document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString()); } //獲取cookie Vue.prototype.getCookie = (name) => { var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)"); if (arr = document.cookie.match(reg)){ return (arr[2]); } return null; } //刪除cookie Vue.prototype.delCookie =(name) => { var exp = new Date(); exp.setTime(exp.getTime() - 1); var cval = this.getCookie(name); if (cval != null){ document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString(); } }

 6.webpack proxyTable 代理跨域

webpack 開發環境可使用proxyTable 來代理跨域,生產環境的話能夠根據各自的服務器進行配置代理跨域就好了。在咱們的項目config/index.js 文件下能夠看到有一個proxyTable的屬性,咱們對其簡單的改寫:

proxyTable: {
    '/api': { target: 'http://api.douban.com/v2', changeOrigin: true, pathRewrite: { '^/api': '' } } }

這樣當咱們訪問localhost:8080/api/movie的時候 其實咱們訪問的是http://api.douban.com/v2/movie這樣便達到了一種跨域請求的方案。

固然咱們也能夠根據具體的接口的後綴來匹配代理,如後綴爲.shtml,代碼以下:

proxyTable: {
    '**/*.shtml': { target: 'http://192.168.198.111:8080/abc', changeOrigin: true } }

可參考地址:

 7.vue和mintui-Loadmore結合實現下拉刷新,上拉加載 (待優化)

mintui是餓了麼團隊針對vue開發的移動端組件庫,方便實現移動端的一些功能,這裏只用了Loadmore功能實現移動端的上拉分頁刷新,下拉加載數據.
mintui官網:http://mint-ui.github.io/#!/zh-cn

<template>  
  <div class="main-body" :style="{'-webkit-overflow-scrolling': scrollMode}">  
    <v-loadmore :top-method="loadTop" :bottom-method="loadBottom" :bottom-all-loaded="allLoaded" :auto-fill="false" ref="loadmore">  
      <ul class="list" v-for="(val, key) in pageList">  
        <li>  
          <div>我是小11</div>  
          <div>我是小11</div>  
        </li>  
      </ul>  
    </v-loadmore>  
  </div>  
</template>  
<script>  
  import {Loadmore} from 'mint-ui'; export default { data:function() { return { searchCondition:{ //分頁屬性 pageNo:"1", pageSize:"10" }, pageList:[], allLoaded: false, //是否能夠上拉屬性,false能夠上拉,true爲禁止上拉,就是不讓往上劃加載數據了 scrollMode:"auto" //移動端彈性滾動效果,touch爲彈性滾動,auto是非彈性滾動  } }, components: { 'v-loadmore':Loadmore // 爲組件起別名,vue轉換template標籤時不會區分大小寫,例如:loadMore這種標籤轉換完就會變成loadmore,容易出現一些匹配問題 // 推薦應用組件時用a-b形式起名  }, mounted(){ this.loadPageList(); //初次訪問查詢列表  }, methods: { loadTop:function() { //組件提供的下拉觸發方法 //下拉加載 this.loadPageList(); this.$refs.loadmore.onTopLoaded();// 固定方法,查詢完要調用一次,用於從新定位  }, loadBottom:function() { // 上拉加載 this.more();// 上拉觸發的分頁查詢 this.$refs.loadmore.onBottomLoaded();// 固定方法,查詢完要調用一次,用於從新定位  }, loadPageList:function (){ // 查詢數據 this.api.PageList(this.searchCondition).then(data =>{ // 是否還有下一頁,加個方法判斷,沒有下一頁要禁止上拉 this.isHaveMore(data.result.haveMore); this.pageList = data.result.pageList; this.$nextTick(function () { // 原意是DOM更新循環結束時調用延遲迴調函數,大意就是DOM元素在由於某些緣由要進行修改就在這裏寫,要在修改某些數據後才能寫, // 這裏之因此加是由於有個坑,iphone在使用-webkit-overflow-scrolling屬性,就是移動端彈性滾動效果時會屏蔽loadmore的上拉加載效果, // 花了很久才解決這個問題,就是用這個函數,意思就是先設置屬性爲auto,正常滑動,加載完數據後改爲彈性滑動,安卓沒有這個問題,移動端彈性滑動體驗會更好 this.scrollMode = "touch"; }); }); }, more:function (){ // 分頁查詢 this.searchCondition.pageNo = parseInt(this.searchCondition.pageNo) + 1; this.api.loadPageList(this.searchCondition).then(data=>{ this.pageList = this.pageList.concat(data.result.pageList); this.isHaveMore(data.result.haveMore); }); }, isHaveMore:function(isHaveMore){ // 是否還有下一頁,若是沒有就禁止上拉刷新 this.allLoaded = true; //true是禁止上拉加載 if(isHaveMore){ this.allLoaded = false; } } } } </script>

PS:有個坑必定要注意就是註釋裏說的iPhone裏loadmore和-webkit-overflow-scrolling屬性衝突沒法上拉問題

可參考另一個插件,沒有使用過,《簡單靈活且強大的Vue下拉刷新組件:vue-pull-to》

8.vue非父子組件通訊

若是2個組件不是父子組件那麼如何通訊呢?這時能夠經過eventHub來實現通訊。所謂eventHub就是建立一個事件中心,至關於中轉站,能夠用它來傳遞事件和接收事件。

方式一
組件1觸發:

<div @click="eve"></div>
methods: {
    eve() {
        Hub.$emit('change','hehe'); //Hub觸發事件
    }
}

組件2接收:

created() {
    Hub.$on('change', (msg) => { //Hub接收事件
        this.msg = msg; }); }

 可參考:vue非父子組件怎麼進行通訊

方式二

把中轉站數據存放到根實例下面,以下:

// 根組件(this.$root)
new Vue({
 el: '#app', router, render: h => h(App), data: { // 空的實例放到根組件下,全部的子組件都能調用 Bus: new Vue() } })

組件1觸發:

<div @click="eve"></div>
methods: {
    eve() {
        this.$root.Bus.$emit('change','hehe'); } }

組件2接收:

created() {
    this.$root.Bus.$on('change', (msg) => { //接收事件
        this.msg = msg; }); }

注:官方推薦的eventbus 解決方案的缺陷在於, 在數據傳遞過程當中,兩個組件必須都已經被渲染過。

 9.IE9報vuex requires a Promise polyfill in this browser問題解決

由於使用了 ES6 中用來傳遞異步消息的的Promise,而IE低版本的瀏覽器不支持。

解決方法
第一步: 安裝 babel-polyfill 

babel-polyfill能夠模擬ES6使用的環境,可使用ES6的全部新方法

npm install --save-dev babel-polyfill

第二步: 在 Webpack/Browserify/Node中使用

在webpack.config.js文件中把

module.exports = {
    entry: {
        app: './src/main.js' } }

替換爲:

module.exports = {
    entry: {
        app: ["babel-polyfill", "./src/main.js"] } };

固然還有其它兩種引入方式:

  • require("babel-polyfill");
  • import "babel-polyfill";

10.啓動Vue項目時提示: [BABEL] ... max of "500KB".

在項目的根目錄下找到 .babelrc 文件,增長 "compact": false ,如:

{
  "compact": false, "presets": ["env", "react", "stage-0"], "plugins": [ "transform-runtime" ] }

若是不存在則手動建立該文件,並填寫內容如:

{
  "compact": false }

 11.在main.js中監聽微信瀏覽器返回按鈕,讓其不能返回

if(from.name == 'staffInfo' && to.name == 'Login'){
    next({path:'/staffInfo',query:{redirect:from.fullPath}}); }else if(from.name == 'acountFill' && to.name == 'Login'){ next({path:'/acount/acountFill',query:{redirect:from.fullPath}}); }

12.pdf.js默認不顯示電子簽章(數字簽名)問題解決

1. pdfjs 舊版本
pdf.worker.js 找到

if(this.data.fieldType === 'Sig') {
    warn('unimplemented annotation type: Widget signature'); return false; }

註解上面代碼.
2. pdfjs 新 版本v1.10.88
pdf.worker.js 找到

if(data.fieldType === 'Sig') {
    _this2.setFlags(_util.AnnotationFlag.HIDDEN);
} 

13.pdf.js預覽,中文顯示亂碼解決方法

有多是有pdf不支持的字體格式,引入pdf.js的字體試試

const CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.489/cmaps/';
pdfjsLib.getDocument({
    data: pdfData,
    cMapUrl: CMAP_URL,
    cMapPacked: true, })

14.解決Vue引入百度地圖JSSDK:BMap is undefined 問題

export default {
  init: function (){ //console.log("初始化百度地圖腳本..."); const AK = "AK密鑰"; const BMap_URL = "https://api.map.baidu.com/api?v=2.0&ak="+ AK +"&s=1&callback=onBMapCallback"; return new Promise((resolve, reject) => { // 若是已加載直接返回 if(typeof BMap !== "undefined") { resolve(BMap); return true; } // 百度地圖異步加載回調處理 window.onBMapCallback = function () { console.log("百度地圖腳本初始化成功..."); resolve(BMap); }; // 插入script腳本 let scriptNode = document.createElement("script"); scriptNode.setAttribute("type", "text/javascript"); scriptNode.setAttribute("src", BMap_URL); document.body.appendChild(scriptNode); }); } } 

說明:

  • 直接使用官網提供的引用地址:http://api.map.baidu.com/api?v=2.0&ak=您的密鑰
  • 啓用 callback 參數,異步加載必須使用此參數才能夠生效
  • 啓用 https 配置,經過 s=1 參數實現
  • API版本爲2.0,經測試使用,發現3.0版本在HTTPS環境下是有問題的,腳本內部某些請求固定使用HTTP,沒法正常使用。

參考地址:http://www.javashuo.com/article/p-gkqnorig-bx.html

15.本地啓動vue項目,host配置域名訪問出現Invalid Host header 服務器域名訪問出現的問題

在webpack.dev.config.js中找到 devServer下的hot,再下面添加 disableHostCheck: true,來解決127.0.0.1指向其餘域名時出現"Invalid Host header"問題

如圖所示:

16.vue項目中在使用vue-router切換頁面的時候滾動條怎樣自動滾動到頂部?

有時候咱們須要頁面滾動條滾動到某一固定的位置,通常使用Window scrollTo() 方法。

語法就是:scrollTo(xpos,ypos)

xpos:必需。要在窗口文檔顯示區左上角顯示的文檔的 x 座標。

ypos:必需。要在窗口文檔顯示區左上角顯示的文檔的 y 座標。

例如滾動內容的座標位置100,500:

window.scrollTo(100,500);

好了,這個scrollTop這兒只是簡單介紹一下,下面咱們介紹下veu-router中的滾動行爲。

使用前端路由,當切換到新路由時,想要頁面滾到頂部,或者是保持原先的滾動位置,就像從新加載頁面那樣。 vue-router 能作到,並且更好,它讓你能夠自定義路由切換時頁面如何滾動。

注意: 這個功能只在 HTML5 history 模式下可用。

當建立一個 Router 實例,你能夠提供一個 scrollBehavior 方法:

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    // return 指望滾動到哪一個的位置
 } })

scrollBehavior 方法接收 to 和 from 路由對象。第三個參數 savedPosition 當且僅當 popstate 導航 (經過瀏覽器的 前進/後退 按鈕觸發) 時纔可用。

這個方法返回滾動位置的對象信息,長這樣:

  • { x: number, y: number }
  • { selector: string, offset? : { x: number, y: number }} (offset 只在 2.6.0+ 支持)

若是返回一個 falsy (譯者注:falsy 不是 false參考這裏)的值,或者是一個空對象,那麼不會發生滾動。

舉例:

scrollBehavior (to, from, savedPosition) {
  return { x: 0, y: 0 } }

對於全部路由導航,簡單地讓頁面滾動到頂部。

返回 savedPosition,在按下 後退/前進 按鈕時,就會像瀏覽器的原生表現那樣

scrollBehavior (to, from, savedPosition) {
  if (savedPosition) { return savedPosition } else { return { x: 0, y: 0 } } }

若是你要模擬『滾動到錨點』的行爲:

scrollBehavior (to, from, savedPosition) {
  if (to.hash) { return { selector: to.hash } } }

咱們還能夠利用路由元信息更細顆粒度地控制滾動。

 routes: [
    { path: '/', component: Home, meta: { scrollToTop: true }}, { path: '/foo', component: Foo }, { path: '/bar', component: Bar, meta: { scrollToTop: true }} ]

完整的例子:

import Vue from 'vue'
import VueRouter from 'vue-router' Vue.use(VueRouter) const Home = { template: '<div>home</div>' } const Foo = { template: '<div>foo</div>' } const Bar = { template: ` <div> bar <div style="height:500px"></div> <p id="anchor">Anchor</p> </div>  ` } // scrollBehavior: // - only available in html5 history mode // - defaults to no scroll behavior // - return false to prevent scroll const scrollBehavior = (to, from, savedPosition) => { if (savedPosition) { // savedPosition is only available for popstate navigations. return savedPosition } else { const position = {} // new navigation. // scroll to anchor by returning the selector if (to.hash) { position.selector = to.hash } // check if any matched route config has meta that requires scrolling to top if (to.matched.some(m => m.meta.scrollToTop)) { // cords will be used if no selector is provided, // or if the selector didn't match any element. position.x = 0 position.y = 0 } // if the returned position is falsy or an empty object, // will retain current scroll position. return position } } const router = new VueRouter({ mode: 'history', base: __dirname, scrollBehavior, routes: [ { path: '/', component: Home, meta: { scrollToTop: true }}, { path: '/foo', component: Foo }, { path: '/bar', component: Bar, meta: { scrollToTop: true }} ] }) new Vue({ router, template: ` <div id="app"> <h1>Scroll Behavior</h1> <ul> <li><router-link to="/">/</router-link></li> <li><router-link to="/foo">/foo</router-link></li> <li><router-link to="/bar">/bar</router-link></li> <li><router-link to="/bar#anchor">/bar#anchor</router-link></li> </ul> <router-view class="view"></router-view> </div>  ` }).$mount('#app')

在網上查了一下,網友說還能夠試試在main.js入口文件配合vue-router寫這個

router.afterEach((to,from,next) => {
    window.scrollTo(0,0); });

 17.tips:webpack中alias配置中的「@」的做用

如題所示,build文件夾下的webpack.base.conf.js

resolve: {
    extensions: ['.js', '.vue', '.json'], alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src') } }

其中的@的意思是:只是一個別名而已。這裏設置別名是爲了讓後續引用的地方減小路徑的複雜度。

//例如
src
- components - a.vue - router - home - index.vue index.vue 裏,正常引用 A 組件: import A from '../../components/a.vue' 若是設置了 alias 後。 alias: { 'vue$': 'vue/dist/vue.esm.js', '@': resolve('src') } 引用的地方路徑就能夠這樣了 import A from '@/components/a.vue' 這裏的 @ 就起到了【resolve('src')】路徑的做用。

 18.tips:package.json中的dependencies與devDependencies之間的區別

–save-dev 和 –save 的區別

咱們在使用npm install 安裝模塊或插件的時候,有兩種命令把他們寫入到 package.json 文件裏面去,好比:

  • –save-dev 安裝的 插件,被寫入到 devDependencies 對象裏面去

  • –save 安裝的 插件 ,被寫入到 dependencies 對象裏面去

devDependencies 是隻會在開發環境下依賴的模塊,生產環境不會被打入包內。

dependencies 是不只在開發環境使用,在生成環境也須要。

 19.tips:package.json設置環境變量

三種方法能夠在package.json設置環境變量。

先安裝cross-env:

npm install --save-dev cross-env

package.json設置:

{
  "scripts": { "dev1": "export WEBPACK_ENV=production && npx webpack -p", ## mac "dev1": "set WEBPACK_ENV=production && npx webpack -p", ## windows "dev2": "cross-env CURRENT_ENV=development webpack-dev-server --inline --progress", ## 兼容全部平臺 } }

設置環境變量的做用:

在項目的js腳本中,經過process.env這個對象就能夠訪問到設置的環境變量結合打包軟件webpack等等,實現不一樣的代碼邏輯:

console.log(process.env.WEBPACK_ENV)
console.log(process.env.CURRENT_ENV)

 擴展參考:阮一峯:npm scripts 使用指南

相關文章
相關標籤/搜索