vue項目問題總結

這篇文章主要總結了一些在項目中遇到的一些小問題以及對應的解決方案,避免往後踩坑,後續補充中,若是你對這些問題有不一樣的解答,歡迎評論javascript

1. 輸入框使用v-model 綁定值,可是不能改變

// 第一種狀況
<el-input v-model="form.title"></el-input>
// 初始化
data () {
    return {
        form: {}
    }
}
// 賦值,其中formData爲父組件傳過來的數據
mounted (){
    this.form.title = this.formData.title
}
// 這裏不生效的緣由爲title沒有初始化
data () {
    return {
        form: {title:''}}
}
// 第二種狀況
在表單中使用時,用:model=""給輸入框賦值
<el-form :model="formData">
   <el-form-item>
      <el-input placeholder="請輸入" :model="formData.value" size="small"/>
   </el-form-item>
</el-form>
// 解決方案,改成
<el-input placeholder="請輸入" v-model="formData.value" size="small"/>
複製代碼

2. 文本內容不對html標籤轉譯

我想要輸入下面的內容,可是保存數據後,就變成了aaahtml

解決辦法: 若是是html內容、javascript、xml或其餘特殊內容,使用<xmp></xmp>
若是是有空格和回車這樣的特殊字符的簡單文本 在文本外加<pre></pre> 標籤前端

3. 基礎導出功能

SensitiveOperationExport(params).then(res => {
    if (res.data.code === '200') {
    // 這裏是導出
      window.location.href = res.data.data.path
      this.$message({
        message: '導出成功!',
        type: 'success'
      })
    } else {
      this.$message.error({message: '導出失敗!'})
    }
  })
複製代碼

4. 使用element table 時,禁用部分複選框

<el-table-column type="selection" align="center" fixed :selectable="selectable"></el-table-column>
複製代碼

官網上有這樣一個操做 selectable, 僅對 type=selection 的列有效,類型爲 Function,Function 的返回值用來決定這一行的 CheckBox 是否能夠勾選vue

5.接口返回的數據爲json類型,展現到表格中時,能夠這樣轉換

// 數據結構 content: "{'title': '這是標題'}"
this.title = JSON.parse(content).title
複製代碼

6. 列表中點擊圖片放大功能

安裝viewer,可支持圖片的切換,旋轉,放大等功能,具體操做文檔可百度查看,使用在頁面中也很是簡單,第一步,全局配置java

// main.js 中引入配置
Viewer.setDefaults({
  'zIndex'9999,
  'inline'false// 是否默認展現縮略圖
  'button'true// 右上角按鈕
  'navbar'true// 底部縮略圖
  'title'true// 當前圖片標題
  'toolbar'true// 底部工具欄
  'tooltip'true// 顯示縮放百分比
  'movable'false// 是否能夠移動
  'zoomable'true// 是否能夠縮放
  'rotatable'true// 是否可旋轉
  'scalable'true// 是否可翻轉
  'transition'true// 使用 CSS3 過分
  'fullscreen'true// 播放時是否全屏
  'keyboard'true// 是否支持鍵盤
  'url''data-source'
})
// 頁面中使用
<viewer>
<img :src="scope.row.content "/>
</viewer>

複製代碼

7. 上移和下移操做

通常來講,上移和下移是掉接口操做的,可是也有不掉接口的web

/ 上移
moveUp (index, row) {
  if (index > 0) {
    let upDate = this.tableData[index - 1]
    this.tableData.splice(index - 11)
    this.tableData.splice(index, 0, upDate)
  }
},
// 下移
moveDown (index, row) {
  if ((index + 1) === this.tableData.length) {
    console.log('已是最後一條,不可下移')
  } else {
    let downDate = this.tableData[index + 1]
    this.tableData.splice(index + 11)
    this.tableData.splice(index, 0, downDate)
  }
}
複製代碼

8. 表格的全選和反選

<el-table :data="tableData" border :select-all="allSelect" @selection-change="changeFun" ref="form" height="700"></el-table>
// tableData 是表格數據
<div>
    <el-button @click="toggleSelect(tableData)">全選</el-button>
    <el-button @click="reverseSelect(tableData)">反選</el-button>
</div>
// 全選
    toggleSelect (rows) {
      if (rows) {
        rows.forEach(row => {
          this.$refs.form.toggleRowSelection(row, !this.allSelect)
        })
        this.allSelect = !this.allSelect
      }
    },
    // 反選
    reverseSelect (rows) {
      let checked = this.data
      if (rows) {
        rows.map(row => {
          checked && checked.map(item => {
            if (row.index !== item.index) {
              this.$refs.form.toggleRowSelection(item, false)
              this.$refs.form.toggleRowSelection(row, true)
            } else {
              this.$refs.form.toggleRowSelection(row, false)
            }
          })
        })
        if (checked.length === 0) {
          rows.forEach(row => {
            this.$refs.form.toggleRowSelection(row, true)
          })
        }
      }
    },
    // 獲取選擇的數據
    changeFun (val) {
      this.data = val
    }
複製代碼

9. 按住說話功能

這個功能依賴於recorder.js, 上一篇文章已經介紹過用法了,這裏就不在細說npm

10. 表格編輯和保存切換

// editColorShow: '' // 設置敏感操做默認顯示編輯
// clearEdit: '000' // 替換editColorShow的值
<el-table-column label="操做" align="center"
    width="200">
    <template slot-scope="scope">
      <el-button size="small" v-if="editColorShow !== scope.$index" type="primary" @click="editColor(scope.$index, scope.row)">編輯</el-button>
      <el-button size="small" v-if="editColorShow === scope.$index" type="primary" @click="submitSettingOperation(scope.$index, scope.row)">保存</el-button>
    </template>
 </el-table-column>
 // 方法中這樣
editColor (index, row) {
  this.editColorShow = index
},
submitSettingOperation (index, data) {
  this.editColorShow = this.clearEdit
 }
複製代碼

11. 深拷貝

第一種:element-ui

function copy(arr{
  var newObj = arr.constructor === Array ? [] : {}
  if (typeof arr === 'object') {
    for (var i in arr) {
      if (typeof arr[i] === 'object') {
        newObj[i] = copy(arr[i])
      }
      newObj[i] = arr[i]
    }
    return newObj
  } else {
    return
  }
}
複製代碼

第二種json

function copy (obj{
 var newObj = obj.constructor === Array ? [] : {}
 newObj = JSON.parse(JSON.stringify(obj))
 return newObj
}
複製代碼

12.表單重置問題

以前重置表單的時候都是this.form.xx='',若是是一兩個還好,可是若是表單不少的話就不是很適用了,發現了一個很便捷的操做,只要一行代碼就搞定了後端

this.$refs['infoForm'].resetFields() 
// 前提是要重置的輸入框必須設置prop屬性才能夠
複製代碼

13. txt文件導出,有兩種方式

第一種 純前端下載

fetch('https://xxxxx.com/' + item.path).then(res => res.blob().then(blob => {
    var a = document.createElement('a')
    var url = window.URL.createObjectURL(blob)
    var filename = 'text.txt'
    a.href = url
    a.download = filename
    a.click()
    window.URL.revokeObjectURL(url)
}))
複製代碼

第二種 獲取到txt的內容後下載

createDownload (fileName, content) {
      var blob = new Blob([content])
      var link = document.createElement('a')
      var bodyEle = document.getElementsByTagName('body')[0]
      link.innerHTML = fileName
      link.download = fileName
      link.href = URL.createObjectURL(blob)
      bodyEle.appendChild(link)
      link.click()
      bodyEle.removeChild(link)
    }
複製代碼

雖然兩種均可以實現下載,可是要保證下載的接口能夠在頁面中訪問到,不會有跨域等問題

14. 導出exel

導出表格這裏提供兩種方法,第一種依賴第三方,首先下載三個依賴
下載Blob.js和Export2Excel.js 兩個文件,引入文件中

// npm install file-saver xlsx script-loader --save
// 導出
    onExportExcel (formName) {
      import('@/vendor/Export2Excel').then(excel => {
// 表格的title
        const tHeader = ['訂單編號''姓名''員工編號''手機號''公司']
// 對應的字段     
        const filterVal = ['sn''user_name''user_no''user_phone''user_company']
        const data = this.formatJson(filterVal, this.dataTable)
        excel.export_json_to_excel({
          header: tHeader,
          data,
          filename`訂單列表`
        })
      })
    },
    formatJson (filterVal, jsonData) {
      let arr = jsonData.map(v => filterVal.map(j => v[j]))
      return arr
    }
複製代碼

第二種 經過vue-json-excel,具體細節可參考vue-json-excel

// 安裝 npm install vue-json-excel,引入
// vue中使用
<download-excel
    class   = "btn btn-default"
    :data   = "json_data"
    :fields = "json_fields"
    worksheet = "My Worksheet"
    name    = "filename.xls">
</download-excel>

data(){
  return {
// 要導出的字段
    json_fields: {
            'Complete name''name',
            'City''city',
            'Telephone''phone.mobile',
            'Telephone 2' : {
                field: 'phone.landline',
                callback: (value) => {
                    return `Landline Phone - ${value}`;
                }
            },
        },
// 要導出的數據
        json_data: [
            {
                'name''Tony Peña',
                'city''New York',
                'country''United States',
                'birthdate''1978-03-15',
                'phone': {
                    'mobile''1-541-754-3010',
                    'landline''(541) 754-3010'
                }
            },
            {
                'name''Thessaloniki',
                'city''Athens',
                'country''Greece',
                'birthdate''1987-11-23',
                'phone': {
                    'mobile''+1 855 275 5071',
                    'landline''(2741) 2621-244'
                }
            }
        ],
        json_meta: [
            [
                {
                    'key''charset',
                    'value''utf-8'
                }
            ]
        ]
}
}
複製代碼

15.導航欄中使用iconfont,選中不變色問題

先來看看對比


項目是基於element-ui開發的,避免不了使用到圖標,因此阿里圖庫是個很好的選擇,這裏遇到的問題是左側導航欄選中後,文字顏色發生變化,可是圖標卻一直不變,通常來講引用阿里圖庫有三種方式:Unicode、Font Class 、symbol;我用的是symbol方式引用,具體以下

1.圖標選用的是svg格式,選擇要使用的圖標,下載svg格式
2.建立icon文件夾用於存放圖標,建立svgIcon文件夾用於使用圖標,使用以下


3.這裏致使圖標不變色的緣由是下載的圖標自己就是帶有顏色的,那麼在經過symbol獲取圖標時會在svg的path中增長fill屬性,致使沒法更改顏色,能夠將圖標中fill屬性置空,這樣就能夠解決了

16. vue模糊搜索路由功能

需求: 導航欄中提供搜索框,可根據輸入的頁面名稱,跳轉到指定頁面,代碼以下

<template>
  <div>
    <el-select
      ref="headerSearchSelect"
      v-model="search"
      :remote-method="querySearch" // 遠程搜索方法
      remote  // 是否爲遠程搜索
      filterable // 是否可搜索
      default-first-option // 輸入框按下回車,返回第一個匹配項,需搭配filterable或remote使用
      placeholder="搜索"
      class="header-search-select"
      @change="change"
    >
      <el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
    </el-select>
  </div>
</template>
<script>
import path from 'path';
export default {
// 獲取到當前帳戶下的全部可見頁面路由
  props: {
    routers: {
      type: Array
    }
  },
  data () {
    return {
      search: '',
      options: [],
      searchPool: []
    }
  },
  computed: {
    routes() {
      return this.routers
    }
  },
  mounted () {
    this.searchPool = this.generateRoutes(this.routes)
  },
  methods: {
    // 遠程搜索
    querySearch (query) {
      if (query !== '') {
        // 數組去重
        this.options = Array.from(new Set(this.searchQuery(query)))
      } else {
        this.options = []
      }
    },
    // 改變時跳轉
    change (val) {
     // 判斷當前頁與搜索的頁面是否一致,如一致則清空不跳轉,反之跳轉
      if (val.path !== this.$router.history.current.path) {
        this.$router.push(val.path)
        // 跳轉路徑後清空搜索框內容,也能夠不清空
        this.search = ''
        this.options = []
      } else {
        this.search = ''
        this.options = []
      }
    },
    // 篩選符合條件的路由
    searchQuery (query) {
      const list = []
      this.searchPool.map(item => {
        item.title.filter(items => {
          if (items.indexOf(query) > -1) {
            list.push(item)
          }
        })
      })
      return list
    },
    // 處理路由數據
    generateRoutes(routes, basePath = '/', prefixTitle = []) {
      let res = []
      for (const router of routes) {
        if (router.hidden) { continue }
        const data = {
          path: path.resolve(basePath, router.path),
          title: [...prefixTitle]
        }
        if (router.meta && router.meta.title) {
          data.title = [...data.title, router.meta.title]
          if (router.redirect !== 'noRedirect') {
            res.push(data)
          }
        }
        // recursive child routes
        if (router.children) {
          const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
          if (tempRoutes.length >= 1) {
            res = [...res, ...tempRoutes]
          }
        }
      }
      return res
    }
  }
}
</script>
複製代碼

須要注意的點是路由的寫法,必定要有對應的title,例如這樣

// 當頁面沒有子級菜單時
{
    path'/log',
    component: Home,
    name: 'Log',
    redirect: '/redirect',
    children: [
      {
        path'index',
        name: 'LogIndex',
        component: _import('log/Index'),
        meta: {
          title: '日誌管理',
          roles: [RoleName.Super, RoleName.AfterSale],
          icon: 'custom-rizhi'
        }
      }
    ]
  }
// 當頁面有子級菜單時
{
    path'/operation',
    component: Home,
    name: 'Operation',
    redirect: '/redirect',
    meta: { title: '運營管理', icon: 'custom-yunying1' },  // 區別在於這裏,有子級的必定要在這加上meta
    children: [
      {
        path'payment',
        name: 'OperationPayment',
        component: _import('operation/Payment'),
        meta: {
          title: '支付管理',
          roles: [RoleName.Operator]  // 可經過roles判斷當前用戶是否有權限查看該頁面
        }
      },
      {
        path'shop',
        name: 'OperationShop',
        component: _import('operation/Shop'),
        meta: {
          title: '店鋪管理',
          roles: [RoleName.Super, RoleName.Operator, RoleName.Staff, RoleName.Marketer]
        }
      },
      {
        path'banner',
        name: 'OperationBanner',
        component: _import('operation/Banner'),
        meta: {
          title: '圖片管理',
          roles: [RoleName.Super, RoleName.Operator, RoleName.Staff, RoleName.Marketer]
        }
      }
    ]
  }
複製代碼

補充幾個關於路由的小問題

  1. <router-link to=""></router-link>: 解析成a標籤,經過to指定跳轉路徑
    <router-view>:視圖渲染組件

  2. 路由引入組件的兩種方式

import app from '@/view/app'
{
  path'/',
  component: app, // 第一種:直接引入
  component: () => import('@/view/app'// 第二種:懶加載
}
複製代碼
  1. 動態路由
{
  path'/argu:name' // name爲動態路由參數
  // 嵌套路由
  path'/parent',
  children: [
    {
      path'/child'
    }
  ],
  // 命名路由
  path'/login',
  name: 'name' // 命名,在router-link中能夠:to="{name: 'login'}"跳轉
}
複製代碼
  1. 命名視圖,可加載多個組件
<router-view/>
<router-view name="email"/>
{
  path: 'names',
  components: {
    default: () => import('@/view/app'),
    email: () => import('@/view/message')
  }
}
複製代碼
  1. 重定向三種寫法
{
  path'/email',
  redirect'/main',  // 第一種
  redirect: {  // 第二種
    name: 'main'
  },
  redirectto => {  // 第三種
    return {
      name'main'
    }
  }
}
複製代碼

6.別名(訪問別名就至關於訪問當前路由)

// 例如,訪問main_index就至關於訪問main
{
  path: '/main',
  alias'/main_index'
}
複製代碼

7.跳轉

this.$router.push('/home'// 可直接跳轉到home頁
// 攜帶參數跳轉一
this.$router.push({
  name: 'home',
  querry: {
    // 參數,顯示在地址欄中
  }
})
// 攜帶參數二
this.$router.push({
  params: {
    // 參數
  }
})
// 攜帶參數三
this.$router.push({
  // 第三種
  name: '我是參數'
  path:`/home${name}`
})
複製代碼

8.替換(push和replace區別)
push瀏覽器會有記錄,返回上一頁,replace會把當前頁當爲父級頁
舉個例子:當前頁爲home,點擊跳轉到about頁,點擊push跳轉後在返回,上一頁爲home
當前頁爲home,點擊跳轉到about頁,點擊replace跳轉後在返回,上一頁爲about
this.$router.replace({
name: 'home'
})

  1. props能夠在router中傳值
{
  path: '/about',
// 第一種
  props: {
    foood: 'apple'
  },
// 第二種
  props: router => {
    food: router.query.food   // 參數中傳遞了food值
  }
}
// 頁面中獲取
props: {
  foood: {
    typestring,
    default'orange'
  }
}
複製代碼
  1. router中配置mode: 'history'能夠去除地址欄#,但須要後端配置支持
    router.before() 前置跳轉,可用於跳轉前判斷是否登陸,是否有權限
相關文章
相關標籤/搜索