亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

vue項目前端知識點整理【收藏】

2019-11-19 11:35:16
字體:
來源:轉載
供稿:網友

微信授權后還能通過瀏覽器返回鍵回到授權頁

在導航守衛中可以在 next({}) 中設置 replace: true 來重定向到改路由,跟 router.replace() 相同

router.beforeEach((to, from, next) => { if (getToken()) { ... } else { // 儲存進來的地址,供授權后跳回 setUrl(to.fullPath) next({ path: '/author', replace: true }) }})

路由切換時頁面不會自動回到頂部

const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { return new Promise((resolve, reject) => {  setTimeout(() => {  resolve({ x: 0, y: 0 })  }, 0) }) }})

ios系統在微信瀏覽器input失去焦點后頁面不會自動回彈

初始的解決方案是input上綁定 onblur 事件,缺點是要綁定多次,且有的input存在于第三方組件中,無法綁定事件。

后來的解決方案是全局綁定 focusin 事件,因為 focusin 事件可以冒泡,被最外層的body捕獲。

util.wxNoScroll = function() { let myFunction let isWXAndIos = isWeiXinAndIos() if (isWXAndIos) {  document.body.addEventListener('focusin', () => {   clearTimeout(myFunction)  })  document.body.addEventListener('focusout', () => {   clearTimeout(myFunction)   myFunction = setTimeout(function() {    window.scrollTo({top: 0, left: 0, behavior: 'smooth'})   }, 200)  }) }  function isWeiXinAndIos () {  let ua = '' + window.navigator.userAgent.toLowerCase()  let isWeixin = /MicroMessenger/i.test(ua)  let isIos = //(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua)  return isWeixin && isIos }}

在子組件中修改父組件傳遞的值時會報錯

vue中的props是單向綁定的,但如果props的類型為數組或者對象時,在子組件內部改變props的值控制臺不會警告。因為數組或對象是地址引用,但官方不建議在子組件內改變父組件的值,這違反了vue中props單向綁定的思想。所以需要在改變props值的時候使用 $emit ,更簡單的方法是使用 .sync 修飾符。

// 在子組件中this.$emit('update:title', newTitle)//在父組件中<text-document :title.sync="doc.title"></text-document>使用微信JS-SDK上傳圖片接口的處理

首先調用 wx.chooseImage() ,引導用戶拍照或從手機相冊中選圖。成功會拿到圖片的 localId ,再調用 wx.uploadImage() 將本地圖片暫存到微信服務器上并返回圖片的服務器端ID,再請求后端的上傳接口最后拿到圖片的服務器地址。

chooseImage(photoMustTake) { return new Promise(resolve => {  var sourceType = (photoMustTake && photoMustTake == 1) ? ['camera'] : ['album', 'camera']  wx.chooseImage({   count: 1, // 默認9   sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,默認二者都有   sourceType: sourceType, // 可以指定來源是相冊還是相機,默認二者都有   success: function (res) {    // 返回選定照片的本地ID列表,localId可以作為img標簽的src屬性顯示圖片    wx.uploadImage({     localId: res.localIds[0],     isShowProgressTips: 1,     success: function (upRes) {      const formdata={mediaId:upRes.serverId}      uploadImageByWx(qs.stringify(formdata)).then(osRes => {       resolve(osRes.data)      })     },     fail: function (res) {     // alert(JSON.stringify(res));     }    });   }  }); })}

聊天室斷線重連的處理

由于后端設置了自動斷線時間,所以需要 socket 斷線自動重連。

在 data 如下幾個屬性, beginTime 表示當前的真實時間,用于和服務器時間同步, openTime 表示 socket 創建時間,主要用于分頁,以及重連時的判斷, reconnection 表示是否斷線重連。

data() { return {  reconnection: false,  beginTime: null,  openTime: null }}

初始化 socket 連接時,將 openTime 賦值為當前本地時間, socket 連接成功后,將 beginTime 賦值為服務器返回的當前時間,再設置一個定時器,保持時間與服務器一致。

發送消息時,當有多個用戶,每個用戶的系統本地時間不同,會導致消息的順序錯亂。所以需要發送 beginTime 參數用于記錄用戶發送的時間,而每個用戶的 beginTime 都是與服務器時間同步的,可以解決這個問題。

聊天室需要分頁,而不同的時刻分頁的數據不同,例如當前時刻有10條消息,而下個時刻又新增了2條數據,所以請求分頁數據時,傳遞 openTime 參數,代表以創建socket的時間作為查詢基準。

// 創建socketcreateSocket() { _that.openTime = new Date().getTime() // 記錄socket 創建時間 _that.socket = new WebSocket(...)}// socket連接成功 返回狀態COMMAND_LOGIN_RESP(data) { if(10007 == data.code) { // 登陸成功  this.page.beginTime = data.user.updateTime // 登錄時間  this.timeClock() }}// 更新登錄時間的時鐘timeClock() { this.timer = setInterval(() => {  this.page.beginTime = this.page.beginTime + 1000 }, 1000)}

當socket斷開時,判斷 beginTime 與當前時間是否超過60秒,如果沒超過說明為非正常斷開連接不做處理。

_that.socket.onerror = evt => { if (!_that.page.beginTime) {  _that.$vux.toast.text('網絡忙,請稍后重試')  return false } // 不重連 if (this.noConnection == true) {  return false } // socket斷線重連 var date = new Date().getTime() // 判斷斷線時間是否超過60秒 if (date - _that.openTime > 60000) {  _that.reconnection = true  _that.createSocket() }}

發送音頻時第一次授權問題

發送音頻時,第一次點擊會彈框提示授權,不管點擊允許還是拒絕都會執行 wx.startRecord() ,這樣再次調用錄音就會出現問題(因為上一個錄音沒有結束), 由于錄音方法是由 touchstart 事件觸發的,可以使用 touchcancel 事件捕獲彈出提示授權的狀態。

_that.$refs.btnVoice.addEventListener("touchcancel" ,function(event) { event.preventDefault() // 手動觸發 touchend _that.voice.isUpload = false _that.voice.voiceText = '按住 說話' _that.voice.touchStart = false _that.stopRecord()})

組件銷毀時,沒有清空定時器

在組件實例被銷毀后, setInterval() 還會繼續執行,需要手動清除,否則會占用內存。

mounted(){ this.timer = (() => {  ... }, 1000)},//最后在beforeDestroy()生命周期內清除定時器 beforeDestroy() { clearInterval(this.timer)   this.timer = null}

watch監聽對象的變化

watch: { chatList: {  deep: true, // 監聽對象的變化  handler: function (newVal,oldVal){   ...  } }}

后臺管理系統模板問題

由于后臺管理系統增加了菜單權限,路由是根據菜單權限動態生成的,當只有一個菜單的權限時,會導致這個菜單可能不顯示,參看模板的源碼:

<router-link v-if="hasOneShowingChildren(item.children) && !item.children[0].children&&!item.alwaysShow" :to="resolvePath(item.children[0].path)"> <el-menu-item :index="resolvePath(item.children[0].path)" :class="{'submenu-title-noDropdown':!isNest}">  <svg-icon v-if="item.children[0].meta&&item.children[0].meta.icon" :icon-class="item.children[0].meta.icon"></svg-icon>  <span v-if="item.children[0].meta&&item.children[0].meta.title" slot="title">{{generateTitle(item.children[0].meta.title)}}</span> </el-menu-item> </router-link> <el-submenu v-else :index="item.name||item.path"> <template slot="title">  <svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"></svg-icon>  <span v-if="item.meta&&item.meta.title" slot="title">{{generateTitle(item.meta.title)}}</span> </template> <template v-for="child in item.children" v-if="!child.hidden">  <sidebar-item :is-nest="true" class="nest-menu" v-if="child.children&&child.children.length>0" :item="child" :key="child.path" :base-path="resolvePath(child.path)"></sidebar-item>  <router-link v-else :to="resolvePath(child.path)" :key="child.name">  <el-menu-item :index="resolvePath(child.path)">   <svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"></svg-icon>   <span v-if="child.meta&&child.meta.title" slot="title">{{generateTitle(child.meta.title)}}</span>  </el-menu-item>  </router-link> </template> </el-submenu>

其中 v-if="hasOneShowingChildren(item.children) && !item.children[0].children&&!item.alwaysShow" 表示當這個節點只有一個子元素,且這個節點的第一個子元素沒有子元素時,顯示一個特殊的菜單樣式。而問題是 item.children[0] 可能是一個隱藏的菜單( item.hidden === true ),所以當這個表達式成立時,可能會渲染一個隱藏的菜單。參看最新的后臺源碼,作者已經修復了這個問題。

<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">  <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /> </el-menu-item> </app-link></template>methods: { hasOneShowingChild(children = [], parent) {  const showingChildren = children.filter(item => {  if (item.hidden) {   return false  } else {   // Temp set(will be used if only has one showing child)   this.onlyOneChild = item   return true  }  })  // When there is only one child router, the child router is displayed by default  if (showingChildren.length === 1) {  return true  }  // Show parent if there are no child router to display  if (showingChildren.length === 0) {  this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }  return true  }  return false } }

動態組件的創建

有時候我們有很多類似的組件,只有一點點地方不一樣,我們可以把這樣的類似組件寫到配置文件中,動態創建和引用組件

var vm = new Vue({ el: '#example', data: { currentView: 'home' }, components: { home: { /* ... */ }, posts: { /* ... */ }, archive: { /* ... */ } }})<component v-bind:is="currentView"> <!-- 組件在 vm.currentview 變化時改變! --></component>

動態菜單權限

由于菜單是根據權限動態生成的,所以默認的路由只需要幾個不需要權限判斷的頁面,其他的頁面的路由放在一個map對象 asyncRouterMap 中,

設置 role 為權限對應的編碼

export const asyncRouterMap = [ {  path: '/project',  component: Layout,  redirect: 'noredirect',  name: 'Project',  meta: { title: '項目管理', icon: 'project' },  children: [   {    path: 'index',    name: 'Index',    component: () => import('@/views/project/index'),    meta: { title: '項目管理', role: 'PRO-01' }   },

導航守衛的判斷,如果有 token 以及 store.getters.allowGetRole 說明用戶已經登錄, routers 為用戶根據權限生成的路由樹,如果不存在,則調用 store.dispatch('GetMenu') 請求用戶菜單權限,再調用 store.dispatch('GenerateRoutes') 將獲取的菜單權限解析成路由的結構。

router.beforeEach((to, from, next) => { if (whiteList.indexOf(to.path) !== -1) {  next() } else {  NProgress.start()  // 判斷是否有token 和 是否允許用戶進入菜單列表  if (getToken() && store.getters.allowGetRole) {   if (to.path === '/login') {    next({ path: '/' })    NProgress.done()   } else {    if (!store.getters.routers.length) {     // 拉取用戶菜單權限     store.dispatch('GetMenu').then(() => {      // 生成可訪問的路由表      store.dispatch('GenerateRoutes').then(() => {       router.addRoutes(store.getters.addRouters)       next({ ...to, replace: true })      })     })    } else {     next()    }   }  } else {   next('/login')   NProgress.done()  } }})

store中的actions

// 獲取動態菜單菜單權限GetMenu({ commit, state }) { return new Promise((resolve, reject) => {  getMenu().then(res => {   commit('SET_MENU', res.data)   resolve(res)  }).catch(error => {   reject(error)  }) })},// 根據權限生成對應的菜單GenerateRoutes({ commit, state }) { return new Promise(resolve => {  // 循環異步掛載的路由  var accessedRouters = []  asyncRouterMap.forEach((item, index) => {   if (item.children && item.children.length) {    item.children = item.children.filter(child => {     if (child.hidden) {      return true     } else if (hasPermission(state.role.menu, child)) {      return true     } else {      return false     }    })   }   accessedRouters[index] = item  })  // 將處理后的路由保存到vuex中  commit('SET_ROUTERS', accessedRouters)  resolve() })},

項目的部署和版本切換

目前項目有兩個環境,分別為測試環境和生產環境,請求的接口地址配在 /src/utils/global.js 中,當部署生產環境時只需要將develop分支的代碼合并到master分支,global.js不需要再額外更改地址

總結

以上所述是小編給大家介紹的vue項目前端知識點整理,希望對大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會及時回復大家的!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性生交大片免网| 精品国产一区二区三区久久狼5月| 欧美在线www| 国产欧美va欧美va香蕉在| 92国产精品久久久久首页| 久久偷看各类女兵18女厕嘘嘘| 日韩国产精品视频| 国产精品久久久久国产a级| 色与欲影视天天看综合网| 国产精品久久久av| 日韩欧美在线第一页| 91影视免费在线观看| 欧美大片va欧美在线播放| 久久久精品电影| 中文字幕国产精品| 伊人久久五月天| 高清欧美一区二区三区| 久久久久久久久中文字幕| 性色av一区二区咪爱| 欧美日韩加勒比精品一区| 51ⅴ精品国产91久久久久久| 一区二区三区高清国产| 欧洲成人免费视频| 成人激情视频小说免费下载| 欧美在线激情网| 亚洲高清一区二| 欧美香蕉大胸在线视频观看| 亚洲欧洲高清在线| 国产欧美欧洲在线观看| 欧美日韩国产精品专区| 亚洲人午夜精品| 欧美激情在线视频二区| 亚洲新声在线观看| 久久99精品国产99久久6尤物| 亚洲国产天堂久久国产91| 色综合伊人色综合网站| 欧美精品18videos性欧美| 清纯唯美亚洲综合| 日韩大片免费观看视频播放| 国产精品www| 九九热最新视频//这里只有精品| 精品久久久久久中文字幕一区奶水| 另类天堂视频在线观看| 日韩欧美国产激情| 韩国视频理论视频久久| 7777kkkk成人观看| 色偷偷偷综合中文字幕;dd| 欧美最顶级丰满的aⅴ艳星| 亚洲一级黄色片| 97国产在线观看| 久久久免费在线观看| 国产欧美日韩精品丝袜高跟鞋| 欧美性xxxxxxx| 欧美制服第一页| 97成人在线视频| 亚洲第一区中文99精品| 国产91精品黑色丝袜高跟鞋| 欧亚精品在线观看| 最好看的2019的中文字幕视频| 亚洲九九九在线观看| 成人精品一区二区三区电影免费| 欧美激情精品在线| 91香蕉嫩草影院入口| 国产精品视频网址| 亚洲精品中文字幕有码专区| 国外成人在线播放| 美日韩丰满少妇在线观看| 韩国精品久久久999| 欧美精品第一页在线播放| 久久久久久香蕉网| www.日韩视频| 最近2019年手机中文字幕| 欧美性猛交99久久久久99按摩| 美女av一区二区三区| 日韩在线播放av| 久久国产精彩视频| 色综合男人天堂| 欧美日韩国产成人在线| 亚洲精品日产aⅴ| 日产精品久久久一区二区福利| 欧美疯狂做受xxxx高潮| 国产精品久久一区主播| 欧美精品中文字幕一区| 亚洲福利视频二区| 国产成人亚洲综合91精品| 色偷偷偷综合中文字幕;dd| 欧美精品999| 成人444kkkk在线观看| 欧美激情一区二区三区久久久| 色诱女教师一区二区三区| 成人性生交大片免费观看嘿嘿视频| 奇米一区二区三区四区久久| 久久男人的天堂| 亚洲在线第一页| 欧美大片va欧美在线播放| 亚洲电影免费观看| 色综合久久中文字幕综合网小说| 国自产精品手机在线观看视频| 国产精品成人v| 精品亚洲va在线va天堂资源站| 久久久久久久久久久免费| 国产精品久久久久久久久久尿| 欧美乱妇40p| 992tv在线成人免费观看| 欧美体内谢she精2性欧美| 欧美猛交免费看| 自拍偷拍亚洲精品| 国产午夜精品免费一区二区三区| 伊人久久五月天| 国产suv精品一区二区三区88区| 国产精品视频一区国模私拍| 久久99精品久久久久久青青91| 最近2019中文字幕第三页视频| 欧美寡妇偷汉性猛交| 色老头一区二区三区在线观看| 欧美极品在线播放| 欧美日韩国产丝袜美女| 欧美激情免费观看| 欧美午夜精品在线| 欧美视频第一页| 成人黄色片在线| 成人h片在线播放免费网站| 日韩经典中文字幕| 日韩一区二区欧美| 亚洲午夜国产成人av电影男同| 欧美在线激情网| 欧美另类第一页| 97在线视频免费观看| 精品国产电影一区| 91po在线观看91精品国产性色| 亚洲aa在线观看| 亚洲国产成人久久综合| 日韩欧美成人区| 美日韩在线视频| 欧美激情精品久久久久久| 国产成人在线一区二区| 亚洲影视九九影院在线观看| 亚洲精品美女在线| 色av中文字幕一区| 久久精品国产亚洲一区二区| 中文国产成人精品久久一| 国产一区二区三区在线看| 日韩欧美国产中文字幕| 亚洲欧美日韩直播| 精品国内产的精品视频在线观看| 亚洲精品免费网站| 亚洲日本成人女熟在线观看| 久久精品国产亚洲精品| 欧美日韩亚洲成人| 成人做爽爽免费视频| 亚洲欧美日韩中文在线制服| 国产91成人video| 日韩欧美一区二区在线| 日韩欧美国产网站| 精品一区二区三区四区在线| 91精品国产色综合久久不卡98| 国产91网红主播在线观看| 色综合伊人色综合网| 亚洲精品一区中文| 亚洲va久久久噜噜噜久久天堂| 91精品国产99久久久久久| 亚洲黄色免费三级| 亚洲精品一区中文字幕乱码| 欧美激情图片区|