Vue项目小经验

1. 复制

  • template
    <a-button type="primary" @click="copyUrl(item.response)">Copy URL</a-button>
    
  • methods
    copyUrl (shareLink) {
      var input = document.createElement('input')
      input.value = shareLink
      document.body.appendChild(input)
      input.select()
      document.execCommand('Copy')
      document.body.removeChild(input)
      this.$message.success('复制成功')
    }
    
    

2. 图片预览v-viewer

  • 安装 npm install v-viewer -S
  • 引入
    import 'viewerjs/dist/viewer.css'
    import Viewer from 'v-viewer'
    import Vue from 'vue'
    Vue.use(Viewer)
    
  • 使用
    只需要将v-viewer指令添加到任意元素即可,该元素下的所有img元素都会被viewer自动处理。(放置for循环外,否则无法切换上下张)
    <div v-if="title === '安卓素材'" class="material_box" v-viewer>
      <div v-for="item in recordAndroid" :key="item.id" class="material_item">
        <img :src="item.materialUrl" alt="">
        <div class="btns">
          <a-button type="primary" @click="copyUrl(item.response)">Copy URL</a-button>
        </div>
      </div>
    </div>
    

3. 阻止浏览器自动填充表单

  • bug: 新建账密时自动填充了当前账号的信息
    在这里插入图片描述

  • 解决:

<!-- 阻止浏览器自动填充表单 start-->
<input type="password" class="hide" id="passWord"/>
<input type="text" class="hide" id="userName"/>
<!-- 阻止浏览器自动填充表单 end-->
<a-form-item label='用户名' v-bind="formItemLayout" :validateStatus="validateStatus" :help="help">
  <a-input type="text" @blur="handleUserNameBlur" placeholder="用户名不能少于4个字符" v-decorator="['username',{rules: [{ required: true, message: '用户名不能为空'}]}]"/>
</a-form-item>
<a-form-item label='密码' v-bind="formItemLayout">
    <a-input type='password' placeholder="至少6位密码,区分大小写"
      v-decorator="[
        'password',
        {rules: [
          { required: true, message: '密码不能为空'},
          { min: 6, message: '至少6位密码'},
          { validator: this.handlePasswordLevel }],validateTrigger: ['change','blur']}]"/>
</a-form-item>

将迷惑浏览器的两个input框隐藏掉
.hide{
  width: 0;
  position: absolute;
  border: transparent;
}
  • 注意 '假’input框的id不要和真input的id重复哦
    在这里插入图片描述

4. 禁止表单自动提示

  • 像这样~
    在这里插入图片描述
  • 解决: autocomplete="off"属性

可以写在input上
在这里插入图片描述
也可以写在form上
html <a-form :form="form" autocomplete="off">

5. 图片在固定的盒子里自适应

  • css
img {
      width: auto;
      height: auto;
      max-height: 100%;
      max-width: 100%;
    }
  • 效果
    在这里插入图片描述在这里插入图片描述

6. 新旧密码及强度验证

<template>
<div>
  <!-- 密码修改 -->
  <a-modal
    title="密码修改"
    :keyboard="false"
    :maskClosable="false"
    :closable="false"
    v-model="show"
    @cancel="cancelUpdatePassword"
    @ok="handleUpdatePassword">
    <a-form :autoFormCreate="(form)=>{this.form = form}">
      <a-form-item
        label='旧密码'
        v-bind="formItemLayout"
        fieldDecoratorId="oldPassword"
        :fieldDecoratorOptions="{rules: [{ required: true, message: '请输入旧密码'}, { validator: this.handleOldPassowrd }], validateTrigger: ['blur']}">
        <a-input type="password"
                 autocomplete="false"
                 v-model="oldPassword"
                 placeholder="请输入旧密码"></a-input>
      </a-form-item>
      <a-popover placement="rightTop" trigger="click" :visible="state.passwordLevelChecked">
        <template slot="content">
          <div :style="{ width: '240px' }">
            <div :class="['update-password', passwordLevelClass]">强度:<span>{{ passwordLevelName }}</span></div>
            <a-progress :percent="state.percent" :showInfo="false" :strokeColor=" passwordLevelColor "/>
            <div style="margin-top: 10px;">
              <span>请至少输入 6 个字符。请不要使用容易被猜到的密码。</span>
            </div>
          </div>
        </template>
        <a-form-item
          label='新密码'
          v-bind="formItemLayout"
          fieldDecoratorId="password"
          :fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写'}, { validator: this.handlePasswordLevel }], validateTrigger: ['change', 'blur']}">
          <a-input type="password"
                   @click="handlePasswordInputClick"
                   v-model="newPassword"
                   autocomplete="false"
                   placeholder="至少6位密码,区分大小写"></a-input>
        </a-form-item>
      </a-popover>
      <a-form-item
        label='再次确认'
        v-bind="formItemLayout"
        fieldDecoratorId="password2"
        :fieldDecoratorOptions="{rules: [{ required: true, message: '至少6位密码,区分大小写' }, { validator: this.handlePasswordCheck }], validateTrigger: ['change', 'blur']}">
        <a-input type="password" autocomplete="false" placeholder="确认密码"></a-input>
      </a-form-item>
    </a-form>
  </a-modal>
</div>
</template>
<script>
const formItemLayout = {
  labelCol: { span: 4 },
  wrapperCol: { span: 18 }
}
const levelNames = {
  0: '低',
  1: '低',
  2: '中',
  3: '强'
}
const levelClass = {
  0: 'error',
  1: 'error',
  2: 'warning',
  3: 'success'
}
const levelColor = {
  0: '#ff0000',
  1: '#ff0000',
  2: '#ff7e05',
  3: '#52c41a'
}

export default {
  props: {
    updatePasswordModelVisible: {
      default: false
    },
    user: {
      required: true
    }
  },
  data () {
    return {
      form: null,
      formItemLayout,
      state: {
        passwordLevel: 0,
        passwordLevelChecked: false,
        percent: 10,
        progressColor: '#FF0000'
      },
      oldPassword: '',
      newPassword: '',
      validateStatus: '',
      help: ''
    }
  },
  computed: {
    show: {
      get: function () {
        return this.updatePasswordModelVisible
      },
      set: function () {
      }
    },
    passwordLevelClass () {
      return levelClass[this.state.passwordLevel]
    },
    passwordLevelName () {
      return levelNames[this.state.passwordLevel]
    },
    passwordLevelColor () {
      return levelColor[this.state.passwordLevel]
    }
  },
  methods: {
    isMobile () {
      return this.$store.state.setting.isMobile
    },
    cancelUpdatePassword () {
      this.state.passwordLevelChecked = false
      this.form.resetFields()
      this.$emit('cancel')
    },
    handleUpdatePassword () {
      this.form.validateFields((err, values) => {
        if (!err) {
          this.$put('user/password', {
            password: this.newPassword,
            username: this.user.username
          }).then(() => {
            this.state.passwordLevelChecked = false
            this.$emit('success')
            this.form.resetFields()
          })
        }
      })
    },
    handlePasswordLevel (rule, value, callback) {
      let level = 0
      // 判断这个字符串中有没有数字
      if (/[0-9]/.test(value)) {
        level++
      }
      // 判断字符串中有没有字母
      if (/[a-zA-Z]/.test(value)) {
        level++
      }
      // 判断字符串中有没有特殊符号
      if (/[^0-9a-zA-Z_]/.test(value)) {
        level++
      }
      this.state.passwordLevel = level
      this.state.percent = level * 30
      if (level >= 2) {
        if (level >= 3) {
          this.state.percent = 100
        }
        callback()
      } else {
        if (level === 0) {
          this.state.percent = 10
        }
        callback(new Error('密码强度不够'))
      }
    },
    handlePasswordCheck (rule, value, callback) {
      let password = this.form.getFieldValue('password')
      if (value === undefined) {
        callback(new Error('请输入密码'))
      }
      if (value && password && value.trim() !== password.trim()) {
        callback(new Error('两次密码不一致'))
      }
      callback()
    },
    handlePasswordInputClick () {
      if (!this.isMobile()) {
        this.state.passwordLevelChecked = true
        return
      }
      this.state.passwordLevelChecked = false
    },
    handleOldPassowrd (rule, value, callback) {
      let password = this.oldPassword
      if (this.oldPassword.trim().length) {
        this.$get('user/password/check', {
          password: password,
          username: this.user.username
        }).then((r) => {
          if (r.data) {
            callback()
          } else {
            callback(new Error('旧密码不正确'))
          }
        })
      } else {
        callback()
      }
    }
  }
}
</script>
<style lang="less">
  .update-password {
    &.error {
      color: #ff0000;
    }
    &.warning {
      color: #ff7e05;
    }
    &.success {
      color: #52c41a;
    }
  }
</style>

在这里插入图片描述

表格第一行总计

  • 像这样~
    在这里插入图片描述
  • 表头:
    columns () {
      return [{
        title: '日期',
        dataIndex: 'bizDate',
      }, {
        title: '渠道广告位',
        dataIndex: 'channelAdPosition'
      }, {
        title: '渠道',
        dataIndex: 'channelName'
      }, {
        title: '位置',
        dataIndex: 'adTypeName'
      }, {
        title: 'APP名称',
        dataIndex: 'channelAppName'
      }, {
        title: '系统',
        dataIndex: 'os'
      }, {
        title: '请求数',
        dataIndex: 'requestCount'
      }, {
        title: '成功数',
        dataIndex: 'successCount'
      }, {
        title: '失败数',
        dataIndex: 'failCount'
      }, {
        title: '超时数',
        dataIndex: 'timeoutCount'
      }, {
        title: '展现数',
        dataIndex: 'showCount'
      }, {
        title: '点击数',
        dataIndex: 'clickCount'
      }, {
        title: '收益',
        dataIndex: 'income'
      }, {
        title: 'CPC',
        dataIndex: 'cpc'
      }, {
        title: 'CPM',
        dataIndex: 'cpm'
      }]
    },
    
  • 数据处理
fetch (params = {}) {
   this.loading = true
   this.$get('地址', {
     ...params
   }).then((r) => {
     let data = r.data.data
     this.loading = false
     this.dataSource = data
     let requestCount = 0
     let successCount = 0
     let showCount = 0
     let clickCount = 0
     let failCount = 0
     let timeoutCount = 0
     let os = '总计'
     for (var i = 0; i < this.dataSource.length; i++) {
       let item = this.dataSource[i]
       requestCount += item.requestCount
       successCount += item.successCount
       showCount += item.showCount
       clickCount += item.clickCount
       failCount += item.failCount
       timeoutCount += item.timeoutCount
     }
     let arr = {
       clickCount: clickCount,
       os: os,
       requestCount: requestCount,
       showCount: showCount,
       successCount: successCount,
       failCount: failCount,
       timeoutCount: timeoutCount
     }
     this.dataSource.splice(0, 0, arr)
   })
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值