送給萌新的Vue/JS的拷貝大法

前言

常常看到羣裏有萌新提問element相關使用問題,其實官方文檔很詳細了,但爲了照顧萌新們,因此本篇文章就把常見的業務代碼直接拋出來給萌新們直接無門檻使用!javascript

element 動態麪包屑

bread.vuecss

<template>
  <div class="bread">
     <el-breadcrumb class="breadcrumb" separator="/">
            <el-breadcrumb-item v-for='(item,index) of list' :key='index' v-if='item.name'>
                <i class="iconfont" :class="item.meta.icon"></i>
				{{item.name}}
			</el-breadcrumb-item>
    </el-breadcrumb>
  </div>
</template>

<script> export default { name: '', data () { return { list: null, icon:[] } }, created () { this.getBreadcrumb(); }, methods: { getBreadcrumb () { this.icon= JSON.parse(sessionStorage.getItem('menu')) let matched = this.$route.matched.filter(item => item.name); const first = matched[0]; this.list = matched; this.erpName = sessionStorage.getItem('erpName') } }, watch: { $route() { this.getBreadcrumb(); } } } </script>

<style lang="less" scoped> .bread { background-color: #fff; padding: 15px; margin: 10px 0; } </style>
複製代碼

vue-awesome-swiper 輪播圖效果

<!-- 輪播圖開始 -->
<div class="swiper">
  <swiper :options="swiperOption" class="banner">
    <swiper-slide v-for="(item, index) in bannerImg" :key="index"><img :src="item"></swiper-slide>
  </swiper>
</div>
<!-- 輪播圖結束 -->
複製代碼
import {swiper, swiperSlide} from 'vue-awesome-swiper'
export default {
  data() {
    return {
      swiperOption: {
        initialSlide: 1,
        autoplay: {
          delay: 3000,
          stopOnLastSlide: false,
          disableOnInteraction: false,
        },
        autoplayDisableOnInteraction: true,
        loop: true,
        slidesPerView: "auto",
        centeredSlides: true
      }
    }
  },
  components: {
    swiper,
    swiperSlide,
  }
}
複製代碼
.swiper
    width: 100%
    height: px2rem(130px)
    margin-top: px2rem(10px)
    overflow: hidden
    .swiper-slide
      display: inline-block
      width: 80%;
      height: px2rem(130px)
      &.swiper-slide-active
        img
          margin-top: 0
          width: 100%
          height: 100%
      img
        display: block
        margin: 0 auto
        margin-top: 3.5%
        width: 90.625%
        height: 90.625%
        border-radius: 4px
        vertical-align: middle
複製代碼

vue 自定義上傳頭像

<div @click.native="handleUpload">上傳</div>

  <!-- 調用相機/圖庫 -->
  <input type="file" accept="image/*" @change="handleFileChanged" ref="file" hidden>
  <input type="file" accept="image/*" capture="camera" @change="handleFileChanged" ref="camera" hidden>

  <!-- 修改頭像開始 -->
    <mt-popup v-model="avatarShow" position="bottom" popup-transition="popup-fade" class="gender upload">
      <div class="item red" @click="handleCamera()">拍照</div>
      <div class="item" @click="handleImgUpload()">從相冊裏選擇</div>
      <div class="item btn" @click="avatarShow=false">取消</div>
    </mt-popup>
  <!-- 修改頭像結束 -->
複製代碼
import uuid from'uuid'
 export default {
   data() {
     return {
        token: '',
        name: '',
        avatar: '',
        avatarShow: false,
        files: [],
     }
   },
   methods: {
      handleUpload() {
        this.avatarShow = true
      },
      handleImgUpload() { // 調用相片
        this.files= []
        this.$refs.file.click()
        this.avatarShow = false
      },
      handleCamera() { // 調用相機
        this.files= []
        this.$refs.camera.click()
        this.avatarShow = false
      },
      handleFileChanged($event) {
        let file = $event.target.files[0]
        const freader = new FileReader()
        freader.readAsDataURL(file)
        this.files.push(file)
        freader.onload = (e) => {
          this.files.push({
            src: e.target.result
          })
        }

        let formData = new FormData()
        formData.append('file', file)
        formData.append('key', `${this.name+uuid.v4() + '.' + file.type.split('/')[1]}`)
        formData.append('token', this.token)
        let data = this.$axios.post('https://upload.qbox.me', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          }
        })
         data.then(res=>{
          this.avatar = res.key
          this.uploadAvatar()
        })
      },
      getToken () { // 獲取七牛token
        this.$axios.get('api-f/qiniu/uploadToken/4').then((res) => {
          this.token = res.result[0].qiniuToken
          this.name = res.result[0].name
        })
      },
   }
 }
複製代碼

vue element中table 序號累計

<el-table :data="billData" class="table" stripe>
    <el-table-column align="center" type="index" :index="getIndex" width="50" label="#" />
 </el-table>
複製代碼
export default {
  data() {
    return {
      searchParamas: {
        total: 0,
        pageNum: 1,
        pageSize: 10
      },
    }
  },
  methods: {
    getIndex(index) {
      return index + (this.searchParamas.pageNum - 1) * 10 + 1
    },
  }
}
複製代碼

vue移動端適配

index.html加上html

<meta name=viewport content="width=device-width,initial-scale=1,user-scalable=no,viewport-fit=cover">
複製代碼

安裝依賴vue

npm install lib-flexible
複製代碼

main.js引入:java

import 'lib-flexible'
複製代碼

postcss.config.js配置:node

module.exports = {
  "plugins": {
    "postcss-import": {},
    "postcss-url": {},
    "postcss-aspect-ratio-mini": {},
    "postcss-write-svg": { utf8: false },
    "postcss-cssnext": {},
    "postcss-px-to-viewport": {
      viewportWidth: 750, // 視窗的寬度,對應的是咱們設計稿的寬度,通常是750
      viewportHeight: 1334, // 視窗的高度,根據750設備的寬度來指定,通常指定1334,也能夠不配置
      unitPrecision: 3,  // 指定`px`轉換爲視窗單位值的小數位數(不少時候沒法整除)
      viewportUnit: 'vw',  // 指定須要轉換成的視窗單位,建議使用vw
      selectorBlackList: ['.ignore', '.hairlines'], // 指定不轉換爲視窗單位的類,能夠自定義,能夠無限添加,建議定義一至兩個通用的類名
      minPixelValue: 1, // 小於或等於`1px`不轉換爲視窗單位,你也能夠設置爲你想要的值
      mediaQuery: false // 容許在媒體查詢中轉換`px`
    },
    "postcss-viewport-units": {},
  }
}

複製代碼

vue-router 路由攔截

一、to: Route: 即將要進入的目標 路由對象webpack

二、from: Route: 當前導航正要離開的路由ios

三、next: Function: 必定要調用該方法來 resolve 這個鉤子。執行效果依賴 next 方法的調用參數。web

四、next(): 進行管道中的下一個鉤子。若是所有鉤子執行完了,則導航的狀態就是 confirmed (確認的)。vue-router

五、next(false): 中斷當前的導航。若是瀏覽器的 URL 改變了(多是用戶手動或者瀏覽器後退按鈕),那麼 URL 地址會重置到 from 路由對應的地址。

六、next('/') 或者 next({ path: '/' }): 跳轉到一個不一樣的地址。當前的導航被中斷,而後進行一個新的導航

//router.js
router.beforeEach((to, from, next) => {
  if (to.meta.requireAuth) {
    // 判斷該路由是否須要登陸權限
    if (store.state.token) {
      // 經過vuex state獲取當前的token是否存在
      next();
    } else {
      next({
        path: "/login",
        query: { redirect: to.fullPath } // 將跳轉的路由path做爲參數,登陸成功後跳轉到該路由
      });
    }
  } else {
    next();
  }
});
複製代碼

npm經常使用包大全

vue-lazyload 圖片懶加載,功能很全

axios

支持 promise 的 http 庫

amfe-flexible

移動端適配

vue-meta

組件中動態修改 head 標籤裏面的內容

webpack-bundle-analyzer

打包完成後顯示體積相關信息,能夠了解是否重複加載,哪些文件過大等

html-webpack-include-assets-plugin

用於添加 js 或 css 文件路徑

vue-awesome-swiper

移動端輪播圖插件

swiper.animate1.0.3.min.js

動畫過渡插件

vue-wechat-title

微信動態設置標題

uuid

生成 uid(惟一標識符)

md5

md5 加密

weixin-js-sdk

微信的 jssdk 庫(微信分享)

nodemon

用 nodemon 來代替 node 來啓動應用

babel-polyfill

IE9 不支持 Promise,需安裝 babel-polyfill

qs

數據格式轉換插件,配合 axios 使用

vue-contextmenu

右鍵彈出菜單插件

vue-touch

裝了 hammer.js 的方法

vuex-persistedstate

vuex 數據持久化

vconsole

手機端調試 console

vue-pano

全景圖插件

better-scroll

滾動插件

vue-amap

高德地圖

頁面頂部進度條

nprogress

core-decorators / babel-plugin-transform-decorators-legacy

裝飾器

vue微信分享封裝

import api from './api'
import wx from 'weixin-js-sdk'
**
 *分享
 * @param self
 * @param title 標題
 * @param url 連接
 * @param img 圖片
 * @param desc 描述
 */

export const wxShare = (self, title, url, img, desc) => {
  let url = window.location.href;
  let data = {
    url: url
  };
  api(data).then(res => {
    if (res.code === 1) {
      let data = res.data;
      wx.config({
        debug: false, // 開啓調試模式,調用的全部api的返回值會在客戶端alert出來,若要查看傳入的參數,能夠在pc端打開,參數信息會經過log打出,僅在pc端時纔會打印。
        appId: data.appId, // 必填,公衆號的惟一標識
        timestamp: data.timestamp, // 必填,生成簽名的時間戳
        nonceStr: data.nonceStr, // 必填,生成簽名的隨機串
        signature: data.signature, // 必填,簽名,見附錄1
        jsApiList: ["onMenuShareTimeline", "onMenuShareAppMessage"] // 必填,須要使用的JS接口列表,全部JS接口列表見附錄2
      });
      wx.ready(function () {
        wx.onMenuShareTimeline({
          title: title, // 分享標題
          link: url, // 分享連接,該連接域名或路徑必須與當前頁面對應的公衆號JS安全域名一致
          imgUrl: img, // 分享圖標
          success: function () {
            // 用戶確認分享後執行的回調函數
            self.$toast('分享成功!!!');
          },
          cancel: function () {
            // 用戶取消分享後執行的回調函數
            self.$toast('取消分享!!!');
          }
        });
        wx.onMenuShareAppMessage({
          title: title, // 分享標題
          desc: desc, // 分享描述
          link: url, // 分享連接,該連接域名或路徑必須與當前頁面對應的公衆號JS安全域名一致
          imgUrl: img, // 分享圖標
          type: "", // 分享類型,music、video或link,不填默認爲link
          dataUrl: "", // 若是type是music或video,則要提供數據連接,默認爲空
          success: function () {
            // 用戶確認分享後執行的回調函數
            self.$toast('分享成功!!!');
          },
          cancel: function () {
            // 用戶取消分享後執行的回調函數
            self.$toast('取消分享!!!');
          }
        });
      });
    }
  }).catch(err => {
    console.log(err)
  })
};
複製代碼

vue 自動註冊全局組件

/** * 讀取componetns下的vue文件並自動註冊全局組件 */
const requireComponent = require.context('./components', false, /\.vue$/)

requireComponent.keys().forEach(fileName => {

 const componentConfig = requireComponent(fileName)
 const componentName = fileName.replace(/^\.\//, '').replace(/\.vue/, '')

 Vue.component(componentName, componentConfig.default || componentConfig)
})

/** * 讀取./modules下的全部js文件並註冊模塊 */
const requireModule = require.context('./modules', false, /\.js$/)
const modules = {}

requireModule.keys().forEach(fileName => {
 const moduleName = fileName.replace(/(\.\/|\.js)/g, '')
 modules[moduleName] = {
  namespaced: true,
  ...requireModule(fileName).default
 }
})

export default modules

//main.js 文件
import components from './components'
Object.keys(components).forEach((component) => {
  Vue.component(component, components[component])
})
複製代碼

vue+element修改表頭顏色

<el-table :data="tableData" border :header-cell-style="getRowClass">
複製代碼
getRowClass({ row, column, rowIndex, columnIndex }) {
  if (rowIndex === 0) {
    return 'background:#F9F9F9'
  } else {
    return ''
  }
}
複製代碼

vue filter 全局封裝

//filter.js
let _filters = {};
/** * 金額轉化 * @param 金額 */
_filters.money = num => {
  return num ? `¥${num}` : '';
};
/** 格式化時間 * @param {string} date 須要格式化的時間 * @param {string} fmt 想要格式化的格式 yyyy-MM-dd yyyy-MM-dd hh:mm:ss */
_filters.formatDate = (date, fmt = 'yyyy-MM-dd') => {
  let o = {
    'M+': date.getMonth() + 1, //月份
    'd+': date.getDate(), //日
    'h+': date.getHours(), //小時
    'm+': date.getMinutes(), //分
    's+': date.getSeconds(), //秒
    'q+': Math.floor((date.getMonth() + 3) / 3), //季度
    S: date.getMilliseconds() //毫秒
  };
  if (/(y+)/.test(fmt))
    fmt = fmt.replace(
      RegExp.$1,
      (date.getFullYear() + '').substr(4 - RegExp.$1.length)
    );
  for (var k in o)
    if (new RegExp('(' + k + ')').test(fmt))
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length)
      );
  return fmt;
};

_filters.formatTime(time, option) {
  time = +time * 1000
  const d = new Date(time)
  const now = Date.now()

  const diff = (now - d) / 1000

  if (diff < 30) {
    return '剛剛'
  } else if (diff < 3600) { // less 1 hour
    return Math.ceil(diff / 60) + '分鐘前'
  } else if (diff < 3600 * 24) {
    return Math.ceil(diff / 3600) + '小時前'
  } else if (diff < 3600 * 24 * 2) {
    return '1天前'
  }
  if (option) {
    return parseTime(time, option)
  } else {
    return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '時' + d.getMinutes() + '分'
  }
}

_filters.parseTime(time, cFormat) {
  if (arguments.length === 0) {
    return null
  }

  if ((time + '').length === 10) {
    time = +time * 1000
  }

  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'object') {
    date = time
  } else {
    date = new Date(parseInt(time))
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
    let value = formatObj[key]
    if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}
export default Vue => {
  Object.keys(_filters).forEach(key => {
    vue.filter(key, _filters[key]);
  });
};
//main.js
import filters from './filter';
Vue.use(filters);
複製代碼

vue excel 二進制文件下載

this.$axios
  .get(`xxx`, {
    responseType: 'blob'
  })
  .then(res => {
    let blob = new Blob([res])
    const fileName = '庫存票據.xls'
    if ('download' in document.createElement('a')) {
      // 非IE下載
      const elink = document.createElement('a')
      elink.download = fileName
      elink.style.display = 'none'
      elink.href = URL.createObjectURL(blob)
      document.body.appendChild(elink)
      elink.click()
      URL.revokeObjectURL(elink.href) // 釋放URL 對象
      document.body.removeChild(elink)
    } else {
      // IE10+下載
      navigator.msSaveBlob(blob, fileName)
    }
  })
複製代碼

vue 驗證碼上一個/下一個焦點的獲取

<template>
  <div>
    <label for=""><span class="tip">*</span>{{label}}</label>
    <template v-for="i of num" >
      <input type="number" :key="i" @input="maxlength" @keyup="getCode" class="input" :class="classes">
    </template>
  </div>
</template>
複製代碼
export default {
    model: {
      prop: 'value',
      event: 'getValue'
    },
    props: {
      value: {
        type: [Number, String]
      },
      type: { // 類型
        type: String,
        default: 'text' // text與passw兩種類型
      },
      num: {
        type: Number,
        default: 6
      },
      label: {
        type: String,
      },
      clear: { // 清空值
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        arrVal: []
      };
    },
    computed: {
      classes() {
        return this.type === 'password' ? 'point' : '';
      }
    },
    methods: {
      maxlength(e) {
        if (e.target.value.length > 1) {
          e.target.value = e.target.value.slice(0, 1);
        }
      },
      getCode(el) {
        const dom = el.target;
        const nexDom = dom.nextElementSibling;
        if (!/^\d$/.test(dom.value)) {
          dom.value = '';
        }
        if (dom.value) {
          if (this.arrVal.length < this.num) {
            this.arrVal.push(dom.value);
          }
          if (nexDom) {
            nexDom.focus();
          }
        }
        if (el.keyCode === 8 && dom.previousElementSibling) {
          this.arrVal.pop();
          dom.previousElementSibling.focus();
        }
        const strValue = this.arrVal.join('');
        this.$emit('getValue', strValue);
      }
    },
    watch: {
      clear(n) {
        if (n) {
          const dom = this.$refs.input;
          dom.map(item => {
            item.value = '';
          });
        }
      }
    }
  };
複製代碼
.point{
  -webkit-text-security:disc;
  text-security: disc;
  font-size: 24px;
}
複製代碼

使用:

<zy-input type="password" v-model="pwd" label="請輸入支付密碼:"></zy-input>
複製代碼

vue element使用select作模糊搜索

<el-form-item label="所屬企業:">
  <el-select class="input" v-model="form.companyName" filterable @change="getCurrentData($event)" clearable @keyup.native="getUnitList($event)" placeholder="請選擇">
    <el-option v-for="item of company" :key="item.id" :label="item.companyName" :value="item.id">
    </el-option>
  </el-select>
</el-form-item>
複製代碼
export default {
  data() {
    return {
      currentCompany: {},
      company: [],
    }
  },
  methods: {
    getCurrentData(id) { // 獲取當前選中對象
      this.form.companyId = id
      this.currentCompany = this.company.find(item => item.id === id)
    },
    async getUnitList(el) {
      const res = await this.$apis.getUnitList({
        pageNum: 1,
        pageSize: 10,
        companyName: el.target.value
      })
      if(res.code===1) {
        this.company = res.data
      }
    },
  }
}
複製代碼

vue pdf 文件下載

<template>
  <div class="priview_resume_container">
    <div style="font-size: 30px" @click="getResume">點這裏下載</div>
  </div>
</template>
複製代碼
<script>
  export default {
    name: 'priviewResume',
    methods: {
      getResume() {
        this.commonUtils.generateResume(
          $('.priview_resume_container')[0],
          '測試'
        )
      }
    },
    components: {}
  }
</script>
複製代碼
import html2canvas from 'html2canvas'
import JsPDF from 'jspdf'
export const generateResume = (el, name) => {
  html2canvas(el).then(canvas => {
    let contentWidth = canvas.width
    let contentHeight = canvas.height
    //一頁pdf顯示html頁面生成的canvas高度;
    let pageHeight = (contentWidth / 592.28) * 841.89
    //未生成pdf的html頁面高度
    let leftHeight = contentHeight
    //頁面偏移
    let position = 0
    //a4紙的尺寸[595.28,841.89],html頁面生成的canvas在pdf中圖片的寬高
    let imgWidth = 595.28
    let imgHeight = (592.28 / contentWidth) * contentHeight
    let pageData = canvas.toDataURL('image/jpeg', 1.0)
    let pdf = new JsPDF('', 'pt', 'a4')
    //有兩個高度須要區分,一個是html頁面的實際高度,和生成pdf的頁面高度(841.89)
    //當內容未超過pdf一頁顯示的範圍,無需分頁
    if (leftHeight < pageHeight) {
      pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
    } else {
      while (leftHeight > 0) {
        //arg3-->距離左邊距;arg4-->距離上邊距;arg5-->寬度;arg6-->高度
        pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
        leftHeight -= pageHeight
        position -= 841.89
        //避免添加空白頁
        if (leftHeight > 0) {
          //添加新頁
          pdf.addPage()
        }
      }
    }
    pdf.save(`${name}.pdf`)
  })
}
複製代碼

vue 監聽鼠標滾輪方向

Vue.directive('scroll', {
  // 當綁定元素插入到 DOM 中
  inserted: function (el,binding) {
    var cb = binding.value
    el.addEventListener('mousewheel',function(e){
      var direction = e.deltaY>0?'down':'up'
      cb(direction)
    })
  }
})

<div v-scroll="fn">
複製代碼

vue 局部刷新組件

<template>
  <div id="app">
    <router-view  v-if="isRouterActive"/>
  </div>
</template>

<script>
export default {
  name: 'App',
  provide() {
    return {
      reload: this.reload
    }
  },
  data() {
    return {
      isRouterActive: true
    }
  },
  methods: {
    reload() {
      this.isRouterActive = false
      this.$nextTick(() => {
        this.isRouterActive = true
      })
    }
  },
}
</script>
複製代碼
<template>
  <div> <div class="item" v-for="item of num" :key="item">{{item}}</div> <el-button @click="add">添加</el-button> <el-button @click="refresh">刷新</el-button> </div> </template> <script> export default { inject: ['reload'], data() { return { num: 0 } }, methods: { refresh() { this.reload() }, add() { this.num = 6 } }, } </script> 複製代碼

vue input file上傳文件後清空

<form ref="form">
  <input type="file" @change="uploadFile" />
</form>
複製代碼
// 文件上傳成功後
this.$refs.form.reset()
複製代碼

vue 自定義註冊全局函數

/**
 * 付款方狀態
 */
const PAYER_STATUS = {

};
/**
 * 收款方狀態
 */
const PAYEE_STATUS = {

};

export const status = {
  PAYER_STATUS,
  PAYEE_STATUS,
  install(Vue) {
    Vue.prototype.$status = this;
  }
}

//main.js
Vue.use(status);
複製代碼

vue element 表格複選框禁止

<el-table-column type="selection" :selectable="disableCheckbox" width="55">
</el-table-column>
複製代碼
export default {
  methods: {
    disableCheckbox(row, index) {
      if (row.businessStatus === 4 || row.businessStatus === 6) {
        return false
      } else {
        return true
      }
    }
  }
}
複製代碼

vue vue-quill-editor 富文本

//main.js
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor /* { default global options } */)
複製代碼
//組件使用
<template>
  <div>
    <quill-editor
      v-model="form.content"
      ref="myQuillEditor"
      :options="editorOption"
      @change="onEditorChange"
      @blur="onEditorBlur($event)"
      @focus="onEditorFocus($event)"
      @ready="onEditorReady($event)"
    >
    </quill-editor>
    <!-- 上傳圖片 -->
    <el-upload
      class="avatar-uploader"
      action=""
      multiple
      ref="uploadImage"
      accept="image/*"
      :http-request="uploadImage"
      style="display:none"
    >
      <el-button
        size="small"
        type="primary"
        id="imgInput"
        v-loading.fullscreen.lock="fullscreenLoading"
        element-loading-text="插入中,請稍候"
        >點擊上傳</el-button
      >
    </el-upload>
    <!-- 上傳視頻 -->
    <el-dialog
      :show-close="false"
      append-to-body
      title="上傳視頻"
      :visible.sync="dialogVisible"
      center
      width="40%"
    >
      <div class="upload-content">
        <el-upload
          drag
          accept="video/*"
          ref="video"
          action=""
          :http-request="uploadVideo"
        >
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">將文件拖到此處,或<em>點擊上傳</em></div>
        </el-upload>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="upload">確 定</el-button>
      </span>
    </el-dialog>
  </div>
  <script>
    const toolOptions = [
      ['bold', 'italic', 'underline', 'strike'],
      ['blockquote', 'code-block'],
      [{ header: 1 }, { header: 2 }],
      [{ list: 'ordered' }, { list: 'bullet' }],
      [{ script: 'sub' }, { script: 'super' }],
      [{ indent: '-1' }, { indent: '+1' }],
      [{ direction: 'rtl' }],
      [{ size: ['small', false, 'large', 'huge'] }],
      [{ header: [1, 2, 3, 4, 5, 6, false] }],
      [{ color: [] }, { background: [] }],
      [{ font: [] }],
      [{ align: [] }],
      [{ clean: '源碼編輯' }],
      ['link', 'image', 'video'],
      ['sourceEditor'] //新添加的工具
    ]
    export default {
      data() {
        const self = this
        return {
          fullscreenLoading: false,
          editorOption: {
            placeholder: '',
            theme: 'snow', // 主題
            modules: {
              toolbar: {
                container: toolOptions, // 工具欄選項
                handlers: {
                  video: val => {
                    self.dialogVisible = true
                  },
                  image: val => {
                    document.querySelector('.avatar-uploader input').click()
                    console.log(val)
                  }
                } // 事件重寫
              }
            }
          }
        }
      },
      computed: {
        editor() {
          return this.$refs.myQuillEditor.quill
        }
      },
      methods: {
        onEditorBlur(quill) {},
        onEditorFocus(quill) {},
        onEditorReady(quill) {},
        onEditorChange({ quill, html, text }) {
          this.form.content = html
        },
        insertVideo() {
          this.editor.insertEmbed(
            this.editor.selection.savedRange.index,
            'video',
            `${this.$store.state.constant.aliPath}${url}`
          )
        },
        insertImage() {
          this.editor.insertEmbed(
            this.editor.selection.savedRange.index,
            'image',
            `${this.$store.state.constant.aliPath}${url}`
          )
        }
      }
    }
  </script>
</template>
複製代碼

vue 封裝拖曳和點擊上傳文件

<template>
  <div class="zy-upload">
    <div
      class="upload-container"
      @drop="drop($event)"
      @dragenter="dragenter($event)"
      @dragover="dragover($event)"
      @click="handlerFileClick"
    >
      <template v-if="progressStatus===1">
        <zy-img src="upload.png" :type="2" class="upload-img"></zy-img>
        <div class="tip">
          點擊或將文件拖拽至此區域 支持(xls、xlsx)格式的文件
        </div>
      </template>
      <template v-else-if="progressStatus ===2">
        <zy-circle-progress
          v-if="isShow"
          ref="$circle"
          class="progress upload-img"
          :isAnimation="true"
          :isRound="true"
          :width="width"
          :radius="radius"
          :progress="progress"
          :barColor="barColor"
          :duration="duration"
          :delay="delay"
          :timeFunction="timeFunction"
          :backgroundColor="backgroundColor"
        ></zy-circle-progress>
        <div class="tip">
          點擊或將文件拖拽至此區域 支持(xls、xlsx)格式的文件
        </div>
      </template>
      <template v-else>
        <zy-img src="excel.png" :type="2" class="upload-img"></zy-img>
        <div class="tip">
          {{fileName}}
        </div>
      </template>
    </div>
    <input
      @change="handlerUploadFile($event)"
      type="file"
      ref="upload"
      style="display: none"
    />
  </div>
</template>

<script>
  /* eslint-disable*/
  export default {
    data() {
      return {
        fileName: '',
        isShow: true,
        width: 56,
        radius: 3,
        progress: 0,
        duration: 1000,
        delay: 20,
        barColor: '#6BBE4E',
        backgroundColor: '#eee',
        timeFunction: 'cubic-bezier(0.8, 0.01, 0.2, 0.9)',
        progressStatus: 1
      }
    },
    methods: {
      async beforeUpload(content) {
        let params = await this.$store
          .dispatch('getAllOss', 'wind-control-valve/')
          .then(res => {
            return res.data
          })
        params.data.file = content
        let data = await this.$store.dispatch('setParams', params.data)
        let url = params.data.host
        return this.$store.dispatch('upload', { url, data }).then(res => {
          this.progress = res.progress
          this.progressStatus = res.progress < 100 ? 2 : 3
          return res.data
        })
      },
      dragenter(el) {
        el.stopPropagation()
        el.preventDefault()
      },
      dragover(el) {
        el.stopPropagation()
        el.preventDefault()
      },
      drop(el) {
        el.stopPropagation()
        el.preventDefault()
        let dt = el.dataTransfer
        for (let i = 0; i !== dt.files.length; i++) {
          if (
            dt.files[i].type ===
              'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
            dt.files[i].type === 'application/vnd.ms-excel'
          ) {
            this.beforeUpload(dt.files[i]).then(res => {
              console.log('res', res)
            })
            this.fileName = dt.files[i].name
          } else {
            console.warn('文件格式不正確')
          }
        }
      },
      handlerFileClick() {
        this.$refs.upload.click()
      },
      handlerUploadFile(el) {
        if (
          el.target.files[0].type ===
            'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' ||
          el.target.files[0].type === 'application/vnd.ms-excel'
        ) {
          this.beforeUpload(el.target.files[0]).then(res => {
            console.log('res', res)
          })
          this.fileName = el.target.files[0].name
        } else {
          console.warn('文件格式不正確')
        }
      }
    }
  }
</script>

<style scoped lang="scss">
  .zy-upload {
    width: 392px;
    height: 202px;
    background: rgba(255, 255, 255, 1);
    border-radius: 4px;
    border: 1px dashed rgba(151, 151, 151, 1);
    &:hover {
      cursor: pointer;
    }
    .upload-container {
      width: 100%;
      height: 100%;
    }
    .upload-img {
      margin: 50px 0 0 166px;
    }
    .tip {
      width: 156px;
      height: 32px;
      font-size: 12px;
      text-align: center;
      color: rgba(84, 98, 115, 1);
      line-height: 16px;
      margin: 10px 0 0 118px;
    }
  }
</style>
#axios 進度條值
return new Promise((resolve, reject) => {
  let progress = 0
  http
    .post(url, data, {
      headers: {
        'Content-Type': 'multipart/form-data'
      },
      onUploadProgress: progressEvent => {
        // 使用本地 progress 事件
        if (progressEvent.lengthComputable) {
          progress = Math.round(
            (progressEvent.loaded / progressEvent.total) * 100
          )
        }
      }
    })
    .then(res => {
      res.progress = progress
      resolve(res)
    })
    .catch(err => {
      reject(err)
    })
})
複製代碼

vue 結束日期與當前時間倒計時 30m

<template>
  <span v-if="show">{{prifx}}{{time}}</span>
</template>

<script>
  /* eslint-disabled */
  export default {
    data() {
      return {
        time: '',
        flag: false,
        show: false
      }
    },
    mounted() {
      const time = setInterval(() => {
        if (this.flag === true) {
          clearInterval(time)
        }
        this.timeDown()
      }, 1000)
    },
    props: {
      endTime: {
        type: String
      },
      prifx: {
        type: String
      }
    },
    methods: {
      timeDown() {
        if (this.endTime) {
          this.show = true
          const endTime = new Date(this.endTime)
          endTime.setMinutes(endTime.getMinutes() + 30)
          const nowTime = new Date()
          const leftTime = ~~((endTime.getTime() - nowTime.getTime()) / 1000)
          const d = ~~(leftTime / (24 * 60 * 60))
          const h = this.formate(~~((leftTime / (60 * 60)) % 24))
          const m = this.formate(~~((leftTime / 60) % 60))
          const s = this.formate(~~(leftTime % 60))
          if (leftTime <= 0) {
            this.flag = true
            this.show = false
            this.$emit('time-end')
          }
          this.time = `${m}:${s}` // 顯示時間格式
        }
      },
      formate(num) {
        if (num >= 10) {
          return num
        }
        return `0${num}`
      }
    }
  }
</script>
複製代碼

組件調用

<count end-time="2019-04-24 17:07:00"></count>
複製代碼

vue qrcode 生成二維碼

<template>
  <div id="qrCode">
    <div id="code"></div>
    <canvas id="canvas"></canvas>
  </div>
</template>
<style></style>
<script>
  import QRCode from 'qrcode'

  export default {
    props: ['url'],
    data() {
      return {
        msg: 'hello vue',
        codes: ''
      }
    },

    components: {
      QRCode
    },

    methods: {
      useqrcode() {
        let canvas = document.getElementById('canvas')
        QRCode.toCanvas(canvas, this.url || window.location.href, error => {
          if (error) console.error(error)
          console.log('QRCode success!')
        })
      }
    },

    mounted() {
      this.useqrcode()
    }
  }
</script>
複製代碼

vue 監聽滾動條

export default {
  methods: {
    handleScroll() {
      let clientHeight =
        document.documentElement.clientHeight || document.body.clientHeight
      // 設備/屏幕高度
      let scrollObj = document.getElementById(div) // 滾動區域
      // document.documentElement.scrollTop || document.body.scrollTop;
      let scrollTop = scrollObj.scrollTop // div 到頭部的距離
      let scrollHeight = scrollObj.scrollHeight // 滾動條的總高度
      //滾動條到底部的條件
      if (scrollTop + clientHeight == scrollHeight) {
        // div 到頭部的距離 + 屏幕高度 = 可滾動的總高度
      }
    }
  },
  mounted() {
    window.addEventListener('scroll', this.handleScroll, true)
  }
  destroyed() {
    window.removeEventListener("scroll", this.handleScroll);
  }
}
複製代碼

textarea 隨文字自適應高度

<textarea
  ref="textarea"
  disabled
  class="proposal"
  v-model="item.proposal"
></textarea>

<script>
  this.$refs.textarea[0].style.minHeight = `${this.$refs.textarea[0].scrollTop +
    this.$refs.textarea[0].scrollHeight}px`
</script>
複製代碼

結語

以上就是送給萌新的常見業務需求,修修改改應該就能完成需求了,也但願萌新們能快速成長!

相關文章
相關標籤/搜索