vue,echarts...(库/框架)

5/15/2020 公共方法

# vue

# 公共方法挂载方式

# 方式一 直接install

  • 公共方法 common.js
// common.js
export default {
  install(Vue) {
    Vue.prototype.filterParams = function (obj) {
      let paramsObj = {};
      for (let i in obj) {
        // 保留非空串('')参数
        if (obj[i] !== "" ) {
          paramsObj[i] = obj[i];
        }
      }
      // 过滤空参数并转为字符串
      // return JSON.stringify(paramsObj);
      // 过滤空参数返回obj对象
      return paramsObj;
    }
  }
}
  • 使用
// 不用引入,直接使用 this.filterParams()
  let params = this.filterParams({
    // 搜索后数据显示的首页条数
    current: 0,
    size: 10,
    // 搜索的参数
    keyword: this.screenForm.superviseName,
    orderTypeValue: this.screenForm.businessType,
    superviseStatus: this.screenForm.workOrderStatus,
  });

# 方式二 通过main.js注册

  • 公共方法 common.js
// common.js
export default {
  test(){
      return "test"
  },
}

  • 注册到main.js

挂载(注册)在main.js

// main.js
import utils from './common/util/utils.js'
Vue.prototype.$utils = utils
  • 使用

在任意页面中使用

let text = this.$utils.test()

# 方式三 各页面引入

// common.js
export function uniqueArr(arr) {
  return Array.from(new Set(arr))
}
let uniqueArr = arr => {
   return Array.from(new Set(arr))
}
export { uniqueArr }
  • 页面引入 使用
// DemoPage.vue
<script>
import { uniqueArr } from '@/utils/utils'; // A.引用其中某几个方法
//const utils = require('@/utils/utils'); // B.全部引用
export default {
  methods:{
    // A
    let relativePath = uniqueArr([1,11,1,2]);
    // B
    // let relativePath = utils.uniqueArr([1,11,1,2]);
  }
}
</script>

# lodash 引入

// main.js
import _ from 'lodash'
Vue.prototype._ = _

# $bus

// main.js
Vue.prototype.$bus = new Vue()
// 绑定
this.$bus.$emit('dowloadCurrent', this.tableDatas, formHead)
// 使用
this.$bus.$off('dowloadCurrent').$on('dowloadCurrent', (tableDatas, formHead) => {
      //  ······
    })

# 过滤并去除空参数

// common.js
export default {
  install(Vue) {
    Vue.prototype.filterParams = function (obj) {
      let paramsObj = {};
      for (let i in obj) {
        // 保留非空串('')参数
        if (obj[i] !== "" ) {
          paramsObj[i] = obj[i];
        }
      }
      // 过滤空参数并转为字符串
      // return JSON.stringify(paramsObj);
      // 过滤空参数返回obj对象
      return paramsObj;
    }

    Vue.prototype.filterParams0 = function (obj) {
      let paramsObj = {};
      for (let i in obj) {
        // 保留非空串('')和等0参数
        if (obj[i] !== "" ||obj[i] == 0) {
          paramsObj[i] = obj[i];
        }
      }
      return paramsObj;
    }

    Vue.prototype.getArrDifferent = function (a, b) {
      const arr = [...a, ...b];
      const newArr = arr.filter(item => {
        return !(a.includes(item) && b.includes(item));
      });
      return newArr;
    }

  }
}

# 表格高度根据窗口变化自适应改变







 

















































<template >
  <el-table
    border
    stripe
    v-loading="loading"
    :data="tableData"
    :height="tableHeight"
    ref="superviseTable"
    style="width: 100%"
    @select="superviseTableSelect"
    @row-click="openDetail"
    :default-sort="{ prop: 'date', order: 'descending' }"
  >
  // ...
  </el-table>
</template>
<script>
export default {
  name:"page",
  data() {
    return {
      // 表格高初始默认
      tableHeight: 360,
      // 屏幕高
      screenHeight: null,
    }
  },
  watch: {
    // 监听屏幕高改变表格高度
    screenHeight: {
      handler: function (val) {
        this.tableHeight = val - 260;
      },
      immediate: true,
    },
  },
  mounted() {
    // 获取高度
    this.getScreenHeight();
  },
  methods: {
    // 获取屏幕高度方法
    getScreenHeight() {
      // 页面初始时获取屏幕高度
      this.screenHeight = document.body.clientHeight;
      // 屏幕尺寸变化就重新赋值
      window.onresize = () => {
        return (() => {
          this.screenHeight = document.body.clientHeight;
        })();
      };
    },
  },
}
</script>

# 二次封装的element-ui 组件

  • 组件内容
// 分页组件
<template>
  <div :class="{'hidden': hidden}" class="pagination-container">
    <el-pagination
      :background="background"
      :current-page.sync="currentPage"
      :page-size.sync="pageSize"
      :layout="layout"
      :page-sizes="pageSizes"
      :total="total"
      v-bind="$attrs"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    >
    </el-pagination>
  </div>
</template>
<script>

import {scrollTo} from '/scroll-to.js'
export default {
  name: "Pagination",
  props: {
    total: {
      required: true,
      type: Number,
    },
    page: {
      type: Number,
      default: 1,
    },
    limit: {
      type: Number,
      default: 20,
    },
    pageSize: {
      type: Array,
      default() {
        return [10, 20, 30, 40, 50, 60];
      },
    },
    layout: {
      type: String,
      default: "total, size, prev, next, jumper",
    },
    background: {
      type: Boolean,
      default: true,
    },
    autoScroll: {
      type: Boolean,
      default: true,
    },
    hidden: {
      type: Boolean,
      default: true,
    },
  },
  computed: {
    currentPage: {
      get() {
        return this.page;
      },
      set(val) {
        this.$emit("update:page", val);
      },
    },
    pageSize: {
      get() {
        return this.limit;
      },
      set(val) {
        this.$emit("update:limit", val);
      },
    },
  },
  methods: {
    handleSizeChange(val) {
      this.$emit("pagination", { page: this.currentPage, limit: val });
      // 回到顶部
      if (this.autoScroll) {
        scrollTo(0, 800);
      }
    },
    handleCurrentChange(val) {
      this.$emit("pagination", { page: val, limit: this.pageSize });
      // 回到顶部
      if (this.autoScroll) {
        scrollTo(0, 800);
      }
    },
  },
};
</script>
<style scoped>
.pagination-container {
  background: #fff;
  padding: 32px 16px;
}
.pagination-container .hidden {
  display: none;
}
</style>
  • 方法
// scroll-to.js
export function scrollTo(to, duration, callback) {
  const start = position();
  const change = to - start;
  const increment = 20;
  let currentTime = 0;
  duration = (typeof duration === "undefined") ? 500 : duration;
  var animateScroll = function () {
    // increment the time
    currentTime += increment;
    var val = Math.easeInOutQuad(currentTime, start, change, duration);
    moveTo(val);
    if (currentTime < duration) {
      requestAnimationFrame(animateScroll);
    } else {
      if (callback && typeof callback === "function") {
        callback();
      }
    }
  };
  animateScroll();
}
  • 使用
<template>
  <pagination v-show="" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination='getList'>
  </pagination>
</template>
// getList 获取数据列表
<script>
export default {
  data() {
    return {
      // 分页 总条数
      total: 0,
      pageNum: 1,
      pageSize: 20,
    };
  },
  methods: {
    getSearchResult() {
      // params
      // 将分页拼接到 url 中传递给后台
      let page = "pageNum" + this.pageNum + "&pageSize" + this.pageSize;
      // 请求数据接口
      getsearchresult(params, page).then((res) => {
        console.log(res);
        // 后台数据返回的条数
        this.total = res.total;
      });
    },
  },
};
</script>

# common方法

公共方法
/**
 * Created by PanJiaChen on 16/11/18.
 */

/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string}
 */
import request from '@/utils/request'
export function parseTime(time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
  let date
  if (typeof time === 'undefined' || time === null || time === 'null') {
    return ''
  } else if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(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]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    if (result.length > 0 && value < 10) {
      value = '0' + value
    }
    return value || 0
  })
  return time_str
}

/**
 * Parse the time to string
 * @param {(Object|string|number)} time
 * @param {string} cFormat
 * @returns {string}
 */
export function parseTimeMs(time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}.{b}'
  let date
  if (typeof time === 'undefined' || time === null || time === 'null') {
    return ''
  } else if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    b: date.getMilliseconds(),
    a: date.getDay()
  }
  const time_str = format.replace(/{(y|m|d|h|i|s|b|a)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    if (result.length > 0 && value < 10 && result !== '{b}') {
      value = '0' + value
    } else if (result === '{b}') {
      if (value < 10) {
        value = '00' + value
      } else if (value > 9 && value < 100) {
        value = '0' + value
      }
    }
    return value || 0
  })
  return time_str
}
export function parseTimeYRSF(time, cFormat) {
  if (arguments.length === 0) {
    return null
  }
  const format = cFormat || '{m}-{d} {h}:{i}'
  let date
  if (typeof time === 'undefined' || time === null || time === 'null') {
    return ''
  } else if (typeof time === 'object') {
    date = time
  } else {
    if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
      time = parseInt(time)
    }
    if ((typeof time === 'number') && (time.toString().length === 10)) {
      time = time * 1000
    }
    date = new Date(time)
  }
  const formatObj = {
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes()
  }
  const time_str = format.replace(/{(m|d|h|i)+}/g, (result, key) => {
    let value = formatObj[key]
    // Note: getDay() returns 0 on Sunday
    if (key === 'a') {
      return ['日', '一', '二', '三', '四', '五', '六'][value]
    }
    if (result.length > 0 && value < 10 && result !== '{b}') {
      value = '0' + value
    } else if (result === '{b}') {
      if (value < 10) {
        value = '00' + value
      } else if (value > 9 && value < 100) {
        value = '0' + value
      }
    }
    return value || 0
  })
  return time_str
}

/**
 * @param {number} time
 * @param {string} option
 * @returns {string}
 */
export function formatTime(time, option) {
  if (('' + time).length === 10) {
    time = parseInt(time) * 1000
  } else {
    time = +time
  }
  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() +
      '分'
    )
  }
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function getQueryObject(url) {
  url = url == null ? window.location.href : url
  const search = url.substring(url.lastIndexOf('?') + 1)
  const obj = {}
  const reg = /([^?&=]+)=([^?&=]*)/g
  search.replace(reg, (rs, $1, $2) => {
    const name = decodeURIComponent($1)
    let val = decodeURIComponent($2)
    val = String(val)
    obj[name] = val
    return rs
  })
  return obj
}

/**
 * @param {string} input value
 * @returns {number} output value
 */
export function byteLength(str) {
  // returns the byte length of an utf8 string
  let s = str.length
  for (var i = str.length - 1; i >= 0; i--) {
    const code = str.charCodeAt(i)
    if (code > 0x7f && code <= 0x7ff) s++
    else if (code > 0x7ff && code <= 0xffff) s += 2
    if (code >= 0xDC00 && code <= 0xDFFF) i--
  }
  return s
}

/**
 * @param {Array} actual
 * @returns {Array}
 */
export function cleanArray(actual) {
  const newArray = []
  for (let i = 0; i < actual.length; i++) {
    if (actual[i]) {
      newArray.push(actual[i])
    }
  }
  return newArray
}

/**
 * @param {Object} json
 * @returns {Array}
 */
export function param(json) {
  if (!json) return ''
  return cleanArray(
    Object.keys(json).map(key => {
      if (json[key] === undefined) return ''
      return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
    })
  ).join('&')
}

/**
 * @param {string} url
 * @returns {Object}
 */
export function param2Obj(url) {
  const search = url.split('?')[1]
  if (!search) {
    return {}
  }
  return JSON.parse(
    '{"' +
    decodeURIComponent(search)
    .replace(/"/g, '\\"')
    .replace(/&/g, '","')
    .replace(/=/g, '":"')
    .replace(/\+/g, ' ') +
    '"}'
  )
}

/**
 * @param {string} val
 * @returns {string}
 */
export function html2Text(val) {
  const div = document.createElement('div')
  div.innerHTML = val
  return div.textContent || div.innerText
}

/**
 * Merges two objects, giving the last one precedence
 * @param {Object} target
 * @param {(Object|Array)} source
 * @returns {Object}
 */
export function objectMerge(target, source) {
  if (typeof target !== 'object') {
    target = {}
  }
  if (Array.isArray(source)) {
    return source.slice()
  }
  Object.keys(source).forEach(property => {
    const sourceProperty = source[property]
    if (typeof sourceProperty === 'object') {
      target[property] = objectMerge(target[property], sourceProperty)
    } else {
      target[property] = sourceProperty
    }
  })
  return target
}

/**
 * @param {HTMLElement} element
 * @param {string} className
 */
export function toggleClass(element, className) {
  if (!element || !className) {
    return
  }
  let classString = element.className
  const nameIndex = classString.indexOf(className)
  if (nameIndex === -1) {
    classString += '' + className
  } else {
    classString =
      classString.substr(0, nameIndex) +
      classString.substr(nameIndex + className.length)
  }
  element.className = classString
}

/**
 * @param {string} type
 * @returns {Date}
 */
export function getTime(type) {
  if (type === 'start') {
    return new Date().getTime() - 3600 * 1000 * 24 * 90
  } else {
    return new Date(new Date().toDateString())
  }
}

/**
 * @param {Function} func
 * @param {number} wait
 * @param {boolean} immediate
 * @return {*}
 */
export function debounce(func, wait, immediate) {
  let timeout, args, context, timestamp, result

  const later = function () {
    // 据上一次触发时间间隔
    const last = +new Date() - timestamp

    // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
    if (last < wait && last > 0) {
      timeout = setTimeout(later, wait - last)
    } else {
      timeout = null
      // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
      if (!immediate) {
        result = func.apply(context, args)
        if (!timeout) context = args = null
      }
    }
  }

  return function (...args) {
    context = this
    timestamp = +new Date()
    const callNow = immediate && !timeout
    // 如果延时不存在,重新设定延时
    if (!timeout) timeout = setTimeout(later, wait)
    if (callNow) {
      result = func.apply(context, args)
      context = args = null
    }

    return result
  }
}

/**
 * This is just a simple version of deep copy
 * Has a lot of edge cases bug
 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
 * @param {Object} source
 * @returns {Object}
 */
export function deepClone(source) {
  if (!source && typeof source !== 'object') {
    throw new Error('error arguments', 'deepClone')
  }
  const targetObj = source.constructor === Array ? [] : {}
  Object.keys(source).forEach(keys => {
    if (source[keys] && typeof source[keys] === 'object') {
      targetObj[keys] = deepClone(source[keys])
    } else {
      targetObj[keys] = source[keys]
    }
  })
  return targetObj
}

/**
 * @param {Array} arr
 * @returns {Array}
 */
export function uniqueArr(arr) {
  return Array.from(new Set(arr))
}

/**
 * @returns {string}
 */
export function createUniqueString() {
  const timestamp = +new Date() + ''
  const randomNum = parseInt((1 + Math.random()) * 65536) + ''
  return (+(randomNum + timestamp)).toString(32)
}

/**
 * Check if an element has a class
 * @param {HTMLElement} elm
 * @param {string} cls
 * @returns {boolean}
 */
export function hasClass(ele, cls) {
  return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}

/**
 * Add class to element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function addClass(ele, cls) {
  if (!hasClass(ele, cls)) ele.className += ' ' + cls
}

/**
 * Remove class from element
 * @param {HTMLElement} elm
 * @param {string} cls
 */
export function removeClass(ele, cls) {
  if (hasClass(ele, cls)) {
    const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
    ele.className = ele.className.replace(reg, ' ')
  }
}

// 替换邮箱字符
export function regEmail(email) {
  if (String(email).indexOf('@') > 0) {
    const str = email.split('@')
    let _s = ''
    if (str[0].length > 3) {
      for (var i = 0; i < str[0].length - 3; i++) {
        _s += '*'
      }
    }
    var new_email = str[0].substr(0, 3) + _s + '@' + str[1]
  }
  return new_email
}

// 替换手机字符
export function regMobile(mobile) {
  if (mobile.length > 7) {
    var new_mobile = mobile.substr(0, 3) + '****' + mobile.substr(7)
  }
  return new_mobile
}

// 下载文件
export function downloadFile(obj, name, suffix) {
  const url = window.URL.createObjectURL(new Blob([obj]))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  const fileName = parseTime(new Date()) + '-' + name + '.' + suffix
  link.setAttribute('download', fileName)
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}
// 下载文件
export function downloadFilePdf(obj, name) {
  request({
    url: obj,
    method: 'get',
    responseType: 'blob' // 约定是二进制流
  }).then(res => {
    const url = window.URL.createObjectURL(new Blob([res]))
    const link = document.createElement('a')
    link.style.display = 'none'
    link.href = url
    link.setAttribute('download', name)
    document.body.appendChild(link)
    link.click()
    document.body.removeChild(link)
  })

}
// 无日期的文件下载
// 下载文件
export function noDatedownloadFile(obj, name, suffix) {
  const url = window.URL.createObjectURL(new Blob([obj]))
  const link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  const fileName = name + '.' + suffix
  link.setAttribute('download', fileName)
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/**
 * 工单进度判断
 * @param {(Object|string|number)} cutoffTime 工单截止时间
 * @param {(string|number)} warningTime 工单警告时间
 0 超时
 1 正常
 2 预警
 */
// export function time(cutoffTime, warningTime, callback) {
//   let timer
//   timer = setInterval(function(callback) {
//     if (new Date() < new Date(warningTime)) {
//       console.log('正常')
//       callback(1)
//     } else if ((new Date(cutoffTime) > new Date()) && (new Date() > new Date(warningTime))) {
//       console.log('预警')
//       callback(2)
//     } else if (new Date() > new Date(cutoffTime)) {
//       console.log('超时')
//       callback(0)
//       clearInterval(timer)
//     }
//   }, 1000)
// }

export function caseProgress(cutoffTime, warningTime) {
  // let timer, status
  if (cutoffTime && warningTime) {
    // time(cutoffTime, warningTime, function(a) {
    //   console.log(a)
    // })
    if (new Date() < new Date(warningTime)) {
      return 1
    } else if ((new Date(cutoffTime) > new Date()) && (new Date() > new Date(warningTime))) {
      return 2
    } else if (+new Date() === cutoffTime) {
      return 2
    } else if (new Date() > new Date(cutoffTime)) {
      return 0
    }
  } else {
    // status = 1
    return 1
  }
  // return status
}

使用

<template slot-scope="scope">
  <div>
    {{ parseTime(scope.row.startTime, "{y}-{m}-{d}") }}
  </div>
</template>
<script>
// 日期格式化方法
import { parseTime } from "@/utils/index";
export default {
 data() {
    return {
      parseTime,
    }
  }
}
</script>

# element-ui

# vue 框架中用样式穿透修改element样式

注意!

  • vue中最好直接用::v-deep, 在vue3中其他的方式可能会失效!
// 表单边距
::v-deep .el-form-item {
  margin-bottom: 0;
}
  • elementtable 鼠标移入时变色(自定义颜色)
// 固定列背景色
.el-table__fixed-body-wrapper tr.el-table__row td{
    background-color: #fff;
}
// 鼠标移入颜色
.el-table__fixed-body-wrapper tr.el-table__row td,.el-table__body tbody tr.el-table__row.hover-row >td{
    background-color: #fff;
}
  • elementtable 数据不满整页时显示样式,高度拉伸
// 表格高度样式
::v-deep .el-table__body {
  height: 100%;
}

# form 下拉框 树搜索 vue

  <el-row :gutter="20">
    <el-col :xs="24" :sm="24" :md="24" :lg="24" :xl="12">
      <el-form-item label="事项选择" prop="treeValue">
        <el-select
          v-model="envData.treeValue"
          placeholder="请选择事项"
          clearable
          style="width: 100%"
        >
          <el-option
            :key="1"
            hidden
            :value="1"
          />
          <span class="inputOut">
            <el-input
              v-model.trim="filterText"
              class="treeInput"
              placeholder="请输入关键字搜索"
              @keyup.enter.native="searchDataTree(filterText)"
            />
            <i class="el-icon-search searchIcon" @click="searchDataTree(filterText)" />
          </span>
          <el-tree
            highlight-current
            class="filter_Tree"
            :data="treeData"
            :load="loadNode"
            lazy
            :props="defaultProps"
            :filter-node-method="filterNode"
            @node-click="nodeClick"
          >
            <template #default="{data}">
              <div v-html="textHtml(data)" />
            </template>
          </el-tree>
        </el-select>
      </el-form-item>
    </el-col>
  </el-row>
<script>
import {
  findAllTree
} from '@/api/cyythApi/v2/common'
import * as _ from 'lodash'

export default {
  data() {
    return {
      // 下拉组合树数据
      filterText: '',
      treeData: [],
      defaultProps: {
        value: 'code',
        label: 'name'
      },
      rules: {
        // ······
         // 事项分类下拉树
        treeValue: [
          { required: true, message: '请选择事项', trigger: 'change' }
        ],
        // ······
      }

    }
  }
  watch: {
    // 事项选择下拉树值改变时执行搜索
    filterText: {
      handler(newVal) {
        if (newVal === '') {
          this.init()
        } else {
          this.searchDataTree(newVal)
        }
      }
    },
  },
  created(){
      // 下拉树初始加载
    this.init()
  },
  methods(){
      // 下拉组合树
    init() {
      findAllTree({}).then(res => {
        if (res.code === '200') {
          this.treeData = res.data
        }
      })
    },
    searchDataTree(value) {
      if (!value) {
        this.$nextTick(() => {
          this.init()
        })
      } else {
        findAllTree({ name: value }).then(res => {
          if (res.code === '200') {
            this.$nextTick(() => {
              this.treeData = res.data
              this.treeData.forEach(item => {
                item.name = item.namePath.slice(0, item.namePath.length - 1).replace(/\//g, '-')
              })
            })
          }
        })
      }
    },
    // 过滤方法
    filterNode(value, data) {
      if (!value) return true
      return data.label.indexOf(value) !== -1
    },
    // 事项分类和事项名称下拉树懒加载数据
    loadNode(node, resolve) {
      this.$nextTick(() => {
        if (node && node.data && node.data.type && node.data.type !== '2') {
          findAllTree({ parentCode: node.data.code }).then(res => {
            if (res.code === '200') {
              if (res.data.length === 0) {
                this.$set(node.data, 'isParent', 'n')
                this.$message('分类下暂无可选事项数据!')
              } else {
                res.data.forEach(item => {
                  this.$set(item, 'isParent', 'y')
                })
              }
              return resolve(res.data)
            }
          })
        } else {
          return resolve([])
        }
      })
    },
    // 下拉树的值填写到下拉框
    nodeClick(val) {
      // 树中选项为事项是可选中,为分类是不能选中
      if (val.type === '2') {
        // 事项分类赋值
        this.envData.itemCategories = _.compact(val.categoryCodePath.split('/'))
        // 事项名称code赋值
        this.envData.itemCode = val.code
        // 事项选择下拉框展示文字赋值
        this.envData.treeValue = val.namePath.slice(0, val.namePath.length - 1).replace(/\//g, '-')
      }
      if (val.isParent && val.isParent === 'n') {
        this.$message('分类下暂无可选事项数据!')
      }
    },
    // 下拉树搜索时关键字变色
    textHtml(data) {
      let html = ''
      if (this.filterText) {
        const reg = new RegExp(this.filterText, 'g')
        html = data.name.replace(reg, '<span style="font-weight: 700;color: #0170CC;">' + this.filterText + '</span>')
      } else {
        html = '<span>' + data.name
        '</span>'
      }
      return html
    },
  }

}
</script>
// 下拉组合树
.filter_Tree{
  height: 200px;
  overflow: auto;
}
.inputOut{
  position: relative;
  .searchIcon{
    position: absolute;
    top: 4px;
    right: 15px;

  }
}
.treeInput{
  padding: 8px;
  ::v-deep .el-input__inner{
    padding-right: 26px !important;
  }
}
.el-tree{
  font-size: 12px !important;
}
/* 下拉树选中颜色修改,不能加scoped,所以会影响全局 修改此处请到全局修改 - app.vue*/
/* .el-tree-node.is-current > .el-tree-node__content {
    background-color: #ececee !important;
    color:black !important;
} */

# echarts

# echarts 简单使用和自适应窗口大小

See More
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Document</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
            .box {
                width: 100vw;
                height: 100vh;
            }
            #container {
                width: 100%;
                height: 100%;
            }
        </style>
    </head>

    <body>
        <div class="box"><div id="container"></div></div>
    </body>
    <script src="./echarts.js"></script>
    <script>
        //初始化echarts实例
        var myEcharts = echarts.init(document.querySelector("#container"));
        console.log(myEcharts);
        //配置图表(柱形图)的相关数据
        var option = {
            //描述x轴,x轴描述衣物种类
            xAxis: {
                data: ["羊毛衫", "牛仔裤", "阔腿裤", "连衣裙", "羽绒服"],
                boundaryGap: false, //起点为哪 false为原点
                // type: 'category',
            },
            //描述y轴,表示销量
            yAxis: {},
            //title标题,描述柱形图
            title: {
                //标题内容
                text: "10月份销售量统计柱形图",
            },
            // series系列列表
            series: [
                {
                    //图表的类型 bar柱形 pie柄图 line折线图
                    type: "line",
                    //data定义数据
                    data: [20, 32, 10, 25, 45],
                    name: "销量",
                    //点的的颜色
                    itemStyle: {
                        color: "orange",
                    },
                    //附属信息
                    label: {
                        show: true,
                        formatter: [20, 32, 10, 25, 45],
                    },
                    //高亮的样式
                    emphasis: {
                        itemStyle: {
                            color: "red",
                        },
                        label: {
                            show: true,
                            formatter: "高亮的附属信息",
                        },
                    },
                    areaStyle: {}, //折点图变面级图
                    smooth: true, //将直线变为曲线,不加默认直线
                },
            ],
            // legend图例的说明,解释
            legend: {
                data: ["销量"],
            },
            grid: {
                //配置图表的定位
                left: "3%",
                right: "4%",
                bottom: "3%",
                containLabel: true, //自适应对齐
            },
            tooltip: {
                type: true, //默认提示展示 不写也没事
                trigger: "axis",
                axisPointer: {
                    //坐标轴指示器配置项
                    type: "cross", //十字准星指示器   'line' 直线指示器
                    label: {
                        backgroundColor: "#6a7985",
                    },
                },
            },
        };
        //使用刚指定的配置项和数据显示图表
        myEcharts.setOption(option);
    </script>
    <script>
      /*
      echarts基于Canvas,纯Javascript图表库,提供直观,生动,可交互,可个性化定制的数据统计图表
      绘制步骤:
        1.准备一个具备宽高的容器用来盛放图表
        2.初始化一个echarts实例 ->echarts.init(),这个方法需要传dom元素作为参数,dom元素是这个容器
        3.
        */
      // echarts 自适应窗口
      window.onresize = myEcharts.resize;
    </script>
</html>

当页面只有一个图表的时候直接用 window.onresize = myChart.resize 就可以了

  • resize 用来改变图表尺寸,在容器大小发生改变时需要手动调用。
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var option={···};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
window.onresize = myChart.resize;

但是如果一个页面有多个图表的时候就需要用到 addEventListener 了,不然页面上只有一个图表会根据浏览器的变化而自适应。

var myChart = echarts.init(document.getElementById('main'));
var myChartA = echarts.init(document.getElementById('mainA'));
var myChartB = echarts.init(document.getElementById('mainB'));
// 指定图表的配置项和数据
var option={···};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
myChartA.setOption(option);
myChartB.setOption(option);

window.addEventListener("resize",function (){
    myChart.resize();
    myChartA.resize();
    myChartB.resize();
});

或者

window.onresize = function(){
    myChart.resize();
    myChartA.resize();
    myChartB.resize();

# HTML

# 将 html 标签转为字符串

    function HTMLDOMtoString(HTMLDOM) {
        const div = document.createElement("div");
        div.appendChild(HTMLDOM);
        return div.innerHTML;
    }

# 获取 dom 标签的所有属性和属性值

    var div = document.getElementsByTagName("div")[0]

    function HTMLDOMtoString(HTMLDOM) {
        const div = document.createElement("div");
        div.appendChild(HTMLDOM);
        let str = div.innerHTML;
        let num = str.indexOf(">");
        let arr = str.slice(1, num).split(" ").slice(1);
        return arr
    }

    console.log(HTMLDOMtoString(div));

# CSS

TODO

# JS

# 封装 事件绑定和取消事件绑定

//事件绑定
function on(dom, eventType, fn) {
  if(dom.addEventListener) {
      dom.addEventListener(eventType, fn);
  } else {
      if(dom.attachEvent) {
          dom.attachEvent('on' + eventType, fn);
    }
  }
}
//取消事件绑定
function un(dom, eventType, fn) {
  if(dom.removeEventListener) {
      dom.removeEventListener(eventType, fn, false);
  } else {
      if(dom.detachEvent) {
          dom.detachEvent("on" + eventType, fn)
    }
  }

 }

兼容ie的事件绑定

 var div1 = document.getElementById("div1")
        var div2 = document.getElementById("div2")
        function AddEvent(obj, val) {
            function fun(e) {
                console.log(val, "参数")
                if (obj.addEventListener) {
                    event.stopPropagation()
                    // event.preventDefault()
                } else if (obj.attachEvent) {
                    event.cancelBubble = true
                    // event.returnValue = false
                }
            }
            if (obj.addEventListener) {
                obj.addEventListener('click', fun)
            } else if (obj.attachEvent) {
                obj.attachEvent("onclick", fun)
            }
        }
        AddEvent(div1, "div1")
        AddEvent(div2, "div2")

# 封装2 处理js默认事件的代码

/*
  跨浏览器的事件处理程序
  调用时候直接用domEvent.addEvent( , , );直接调用
  使用时候,先用addEvent添加事件,然后在handleFun里面直接写其他函数方法,如getEvent;
  addEventListener和attachEvent---都是dom2级事件处理程序
*/
var domEvent = {
  //element:dom对象,event:待处理的事件,handleFun:处理函数
  //事件名称,不含“on”,比如“click”、“mouseover”、“keydown”等
  addEvent:function(element,event,handleFun){
    // addEventListener----应用于mozilla
    if(element.addEventListener){
      element.addEventListener(event,handleFun,false);
    }// attachEvent----应用于IE
    else if(element.attachEvent){
      element.attachEvent("on"+event,handleFun);
    }// 其他的选择dom0级事件处理程序
    else{
      // element.onclick===element["on"+event];
      element["on"+event] = handleFun;
    }
  },
  //事件名称,含“on”,比如“onclick”、“onmouseover”、“onkeydown”等
  removeEvent:function(element,event,handleFun){
    //removeEventListener----应用于mozilla
    if (element.removeEventListener) {
      element.removeEventListener(event,handleFun,false);
    }//detachEvent----应用于IE
    else if (element.detachEvent) {
      element.detachEvent("on"+event,handleFun);
    }//其他的选择dom0级事件处理程序
    else {
      element["on"+event] = null;
    }
  },
  //阻止事件冒泡
  stopPropagation:function(event){
    if(event.stopPropagation){
      event.stopPropagation();
    }else{
      event.cancelBubble = true;//IE阻止事件冒泡,true代表阻止
    }
  },
  //阻止事件默认行为
  preventDefault:function(event){
    if(event.preventDefault){
      event.preventDefault();
    }else{
      event.returnValue = false;//IE阻止事件冒泡,false代表阻止
    }
  },
  //获得事件元素
  //event.target--非IE
  //event.srcElement--IE
  getElement:function(event){
    return event.target || event.srcElement;
  },
  //获得事件
  getEvent:function(event){
    return event? event : window.event;
  },
  //获得事件类型
  getType:function(event){
    return event.type;
  }
};

# 过滤参数对象的空值

  • 方法
// trimQueryParams.js
export function trimQueryParams(queryParams) {
  if (typeof queryParams !== 'object') {
      return queryParams
  }
  for (let key of Object.keys(queryParams)) {
    if (queryParams[key] && typeof queryParams[key] === 'string') {
        queryParams[key] = queryParams[key].trim()
    }
    if (queryParams[key] && typeof queryParams[key] === 'object') {
        queryParams[key] = trimQueryParams(queryParams[key])
    }
  }
  return queryParams
}
  • 使用

import { trimQueryParams }  from  /-/trimQueryParams.js

trimQueryParams(objval)

# 获取页面每个加载过程

  // 执行时一定是 loading
  console.log(document.readyState)
  // 当页面的readyState 状态发生改变时,readystatechange事件自动触发
  document.onreadystatechange = function () {
      console.log(document.readyState, "---63行")
  }
  // dom tree 加载完成时,DOMContentLoaded事件自动触发
  document.addEventListener("DOMContentLoaded", function () { console.log("doc tree加载完成", "---66行") })
  // 页面彻底加载完成 locd事件,window.onload 固定写法
  window.onload = function () {
      console.log("load 整个页面加载完成")
  }
  // 外部资源 load事件,图片加载完毕后触发
  document.querySelector("img").onload = function () {
      console.log("外部资源加载完成")
  }

# 模拟 DOMContentLoaded 事件的 readystatechange

// 模拟 DOMContentLoaded/ jquery ready
document.onreadystatechange = function () {
  if (document.readyState === "interactive") {
    initApplication();
  }
}

# 模拟 load 事件的 readystatechange

// 模拟 load 事件
document.onreadystatechange = function () {
  if (document.readyState === "complete") {
    initApplication();
  }
}

# 在 DOMContentLoaded 之前

在 DOMContentLoaded 之前使用 readystatechange 作为事件处理程序以插入或修改DOM

document.addEventListener('readystatechange', event => {
  if (event.target.readyState === 'interactive') {
    initLoader();
  }
  else if (event.target.readyState === 'complete') {
    initApp();
  }
});

# 自执行函数循环添加事件(鼠标移入移出)

 var documentFragment = document.createDocumentFragment()
        var ul = document.createElement("ul")
        ul.style.cssText = "list-style :none; padding:0;"
        documentFragment.appendChild(ul)
        var titleArr = ["首页", "视频", "音乐", "我的"]
        for (let i = 0; i < titleArr.length; i++) {
            var li = document.createElement("li")
            li.style.cssText = "display:inline-block;width:100px;height:35px;text-align :center;line-height:35px;background: blue;"
            li.innerHTML = titleArr[i]
            li.onmouseenter = (function (temp) {
                return function () {
                    temp.style.backgroundColor = "red"
                }
            })(li)
            li.onmouseleave = (function (temp) {
                return function () {
                    temp.style.backgroundColor = "blue"
                }
            })(li)
            ul.appendChild(li)
        }
        document.body.appendChild(documentFragment)

# 工厂模式应用(选择礼物并发送)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <!-- <meta http-equiv="refresh" content="5"> -->
    <title>Document</title>
    <style>
        html,
        body,
        h1,
        h2,
        h3,
        h4,
        h5,
        h6,
        div,
        dl,
        dt,
        dd,
        ul,
        ol,
        li,
        p,
        blockquote,
        pre,
        hr,
        figure,
        table,
        caption,
        th,
        td,
        img,
        form,
        fieldset,
        legend,
        input,
        button,
        textarea,
        menu {
            padding: 0;
            margin: 0;
        }

        .container {
            width: 800px;
            height: 300px;
            border: 1px solid blueviolet;
        }

        .c_giftList {
            width: 100%;
            height: 260px;
        }

        .c_giftMenu {
            width: 100%;
            height: 40px;
            border: 1px solid skyblue;
            line-height: 40px;
            position: relative;
        }

        .c_giftMenu .sendGift {
            width: 100px;
            height: 30px;
            font-style: 22px;
            text-align: center;
            line-height: 30px;
            letter-spacing: 5px;
            position: absolute;
            top: 5px;
            right: 5px;
        }

        .dome1 {
            width: 350px;
            height: 120px;
            border: 3px solid orange;
            display: inline-block;
            margin: 2px;
            text-align: center;
            line-height: 120px
        }

        .c_giftList #selectGift {
            border: 3px solid red;
        }
    </style>
</head>

<body>
    <div class="container">
        <div class="c_giftList">
            <!-- 通过后台获取 -->
        </div>
        <div class="c_giftMenu">
            <button class="sendGift">赠送</button>
        </div>
    </div>
    <script>
        var giftListDiv = document.querySelector(".c_giftList");
        var sendGiftBtn = document.querySelector(".sendGift");
        var selectedItem = "";//用户选中的礼物,用来保存类名
        var giftListArr = ["鲜花", "手机", "飞机", "火箭"]
        var giftClass_listArr = ["Flower", "Phone", "Plane", "Huojian"]
        //    选中
        for (let i = 0; i < giftListArr.length; i++) {
            var giftItemDiv = document.createElement("div");
            giftItemDiv.className = giftClass_listArr[i]
            giftItemDiv.innerHTML = giftListArr[i];
            giftItemDiv.classList.add("dome1")
            // 给每个礼物item都添加点击事件,点击时表示选中,再次点击表示取消
            giftItemDiv.onclick = function () {
                var giftListAll = document.querySelectorAll(".c_giftList div")

                for (let j = 0; j < giftListAll.length; j++) {
                    // 如果列表中 不是当前选中的礼物
                    if (giftListAll[j] != this) {
                        // 就清除id
                        giftListAll[j].id = null;
                    }
                }
                // 如果未选中,就选中
                if (this.id == "selectGift") {
                    this.id = null
                    selectedItem = null
                } else {
                    // 如果选中了,取消选中
                    this.id = "selectGift"
                    console.log(this.className.split(" ")[0])
                    selectedItem = this.className.split(" ")[0]
                    // console.log(selectedItem)
                }
            }
            giftListDiv.appendChild(giftItemDiv)

        }
        // 赠送按钮
        sendGiftBtn.onclick = function () {
            // var gift
            // if (selectedItem == "Flower") {
            //     gift = new Flower()
            // } else if (selectedItem == "Phone") {
            //     gift = new Phone()

            // } else if (selectedItem == "Plane") {
            //     gift = new Plane()
            // } else if (selectedItem == "Huojian") {
            //     gift = new Huojian()
            // } else {
            //     alert("选择正确礼物")
            // }

            //🔺🔺🔺 以上方式是普通方式,和下面的方式功能一致,但是,下面的工厂模式可以降低耦合度,可以将公共方法封装 🔺🔺🔺

            // 根据selectdItem 创建相应类型的对象,并执行其send方法
            var gift = giftFactory.createGift(selectedItem)
            gift.send()
        }


        // 创建礼物
        function Gift() { }
        Gift.prototype.send = function () {
            console.log("在页面送出礼物" + this.getGiftName())
        }
        function Flower() {
            var gname = "鲜花"
            this.getGiftName = function () {
                return gname;
            }
        }
        function Phone() {
            var gname = "手机"
            this.getGiftName = function () {
                return gname;
            }
        }
        function Plane() {
            var gname = "飞机"
            this.getGiftName = function () {
                return gname;
            }
        }
        function Huojian() {
            var gname = "火箭"
            this.getGiftName = function () {
                return gname;
            }
        }
        //    建立父子关系
        Flower.prototype = new Gift()
        Phone.prototype = new Gift()
        Plane.prototype = new Gift()
        Huojian.prototype = new Gift()
        // 建立礼物工厂模式
        var giftFactory = {
            createGift: function (selectedItem) {
                var gift;
                switch (selectedItem) {
                    case "Flower":
                        gift = new Flower()
                        break
                    case "Phone":
                        gift = new Phone()
                        break
                    case "Plane":
                        gift = new Plane()
                        break
                    case "Huojian":
                        gift = new Huojian()
                        break
                    default:
                        alert("选择正确的礼物")
                        break
                }
                return gift
            }
        }

    </script>
</body>

</html>

# js截取日期的年月日

 function getYearMonth(date) {
    // 将日期以空格隔开,即['2020-06-13', '17:10:09']
    date = (date + "").split(/[ ]+/);
    let result = [];
    let reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
    // 用截取出来的年月日进行正则表达式匹配
    reg.exec(date[0]);
    result.push(RegExp.$1); //获取匹配到的第一个子匹配,即‘2020’
    result.push(RegExp.$2);
    result.push(RegExp.$3);
    result.push(RegExp.$4);
    return result;
}
console.log(getYearMonth("2020-06-13 17:10:09"));

var dateStr = "2017-10-22";// 只能截取这种格式的字符
var reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/;
console.log(dateStr.match(reg));
console.log(RegExp.$1);
console.log(RegExp.$2);
console.log(RegExp.$3);

# 时间的格式化

// 对Date的扩展,将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子:
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
// (new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18

Date.prototype.Format = function (fmt) { // author: meizz
  var o = {
    "M+": this.getMonth() + 1, // 月份
    "d+": this.getDate(), // 日
    "h+": this.getHours(), // 小时
    "m+": this.getMinutes(), // 分
    "s+": this.getSeconds(), // 秒
    "q+": Math.floor((this.getMonth() + 3) / 3), // 季度
    "S": this.getMilliseconds() // 毫秒
  };
  if (/(y+)/.test(fmt))
    fmt = fmt.replace(RegExp.$1, (this.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;
}

调用:

var time1 = new Date().Format("yyyy-MM-dd");

var time2 = new Date().Format("yyyy-MM-dd hh:mm:ss");

# 获取当前时\将时间戳转换为时间格式

// 获取当前时间,可以存入数据库(除以1000 是为了存储时空间小,精确到秒即可)
  var timer = parseInt(new Date().getTime() / 1000);
  console.log(timer);
// 将数据库中的时间戳,转换为日期时间格式
  // 方法一
  function getTime(nS) {
      var date = new Date(parseInt(nS) * 1000);
      var year = date.getFullYear();
      var mon =
          date.getMonth() + 1 < 10
              ? "0" + (date.getMonth() + 1)
              : date.getMonth() + 1;
      // 将月份个位加 0
      var day = date.getDate();
      var hours = date.getHours();
      var minu = date.getMinutes();
      var sec =
          date.getSeconds().toString().length < 2
              ? "0" + date.getSeconds()
              : date.getSeconds();
      // 秒数 个位加 0

      return (
          year +
          "/" +
          mon +
          "/" +
          day +
          " " +
          hours +
          ":" +
          minu +
          ":" +
          sec
      );
  }
  console.log(getTime(timer));
  // 方法二
  function timestampToTime(timestamp) {
      var date = new Date(timestamp * 1000); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
      var Y = date.getFullYear() + "-";
      var M =
          (date.getMonth() + 1 < 10
              ? "0" + (date.getMonth() + 1)
              : date.getMonth() + 1) + "-";
      var D = date.getDate() + " ";
      var h = date.getHours() + ":";
      var m = date.getMinutes() + ":";
      var s =
          date.getSeconds().toString().length < 2
              ? "0" + date.getSeconds()
              : date.getSeconds();
      console.log(s);
      return Y + M + D + h + m + s;
  }
  console.log(timestampToTime(timer));

# 透明遮罩(兼容IE8+)

请用原生js实现一个函数,给页面制定的任意一个元素添加一个透明遮罩(透明度可变,默认0.2),使这个区域点击无效,要求兼容IE8+及各主流浏览器,遮罩层效果如下图所示

See More
<style>
#target {
    width: 200px;
    height: 300px;
    margin: 40px;
    background-color: tomato;
}
</style>

<div id="target"></div>

<script>
function addMask(elem, opacity) {
    opacity = opacity || 0.2;

    var rect = elem.getBoundingClientRect();
    var style = getComputedStyle(elem, null);

    var mask = document.createElement('div');
    mask.style.position = 'absolute';
    var marginLeft = parseFloat(style.marginLeft);
    mask.style.left = (elem.offsetLeft - marginLeft) + 'px';
    var marginTop = parseFloat(style.marginTop);
    mask.style.top = (elem.offsetTop - marginTop) + 'px';
    mask.style.zIndex = 9999;
    mask.style.opacity = '' + opacity;
    mask.style.backgroundColor = '#000';

    mask.style.width = (parseFloat(style.marginLeft) +
        parseFloat(style.marginRight) + rect.width) + 'px';
    mask.style.height = (parseFloat(style.marginTop) +
        parseFloat(style.marginBottom) + rect.height) + 'px';

    elem.parentNode.appendChild(mask);
}

var target = document.getElementById('target');
addMask(target);

target.addEventListener('click', function () {
    console.log('click');
}, false);
</script>

# 当天星期x

var days = ['日','一','二','三','四','五','六'];
var date = new Date();

console.log('今天是星期' + days[date.getDay()]);

# 为每个postXXX方法增加拦截验证功能

现有一个Page类,其原型对象上有许多以post开头的方法(如postMsg);另有一拦截函数chekc,只返回ture或false.请设计一个函数,该函数应批量改造原Page的postXXX方法,在保留其原有功能的同时,为每个postXXX方法增加拦截验证功能,当chekc返回true时继续执行原postXXX方法,返回false时不再执行原postXXX方法

function Page() {}

Page.prototype = {
  constructor: Page,

  postA: function (a) {
    console.log('a:' + a);
  },
  postB: function (b) {
    console.log('b:' + b);
  },
  postC: function (c) {
    console.log('c:' + c);
  },
  check: function () {
    return Math.random() > 0.5;
  }
}

function checkfy(obj) {
  for (var key in obj) {
    if (key.indexOf('post') === 0 && typeof obj[key] === 'function') {
      (function (key) {
        var fn = obj[key];
        obj[key] = function () {
          if (obj.check()) {
            fn.apply(obj, arguments);
          }
        };
      }(key));
    }
  }
} // end checkfy()

checkfy(Page.prototype);

var obj = new Page();

obj.postA('checkfy');
obj.postB('checkfy');
obj.postC('checkfy');

# 深拷贝函数

See More
    function deepClone(obj) {
        var _toString = Object.prototype.toString;

        // null, undefined, non-object, function
        if (!obj || typeof obj !== 'object') {
            return obj;
        }

        // DOM Node
        if (obj.nodeType && 'cloneNode' in obj) {
            return obj.cloneNode(true);
        }

        // Date
        if (_toString.call(obj) === '[object Date]') {
            return new Date(obj.getTime());
        }

        // RegExp
        if (_toString.call(obj) === '[object RegExp]') {
            var flags = [];
            if (obj.global) { flags.push('g'); }
            if (obj.multiline) { flags.push('m'); }
            if (obj.ignoreCase) { flags.push('i'); }

            return new RegExp(obj.source, flags.join(''));
        }

        var result = Array.isArray(obj) ? [] :
            obj.constructor ? new obj.constructor() : {};

        for (var key in obj ) {
            result[key] = deepClone(obj[key]);
        }

        return result;
    }

    function A() {
        this.a = a;
    }

    var a = {
        name: 'qiu',
        birth: new Date(),
        pattern: /qiu/gim,
        container: document.body,
        hobbys: ['book', new Date(), /aaa/gim, 111]
    };

    var c = new A();
    var b = deepClone(c);
    console.log(c.a === b.a);
    console.log(c, b);

# 实时动态显示年终倒计时

See More
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>test</title>
</head>
<body>
    <span id="target"></span>
<script type="text/javascript">
    // 为了简化。每月默认30天
    function getTimeString() {
        var start = new Date();
        var end = new Date(start.getFullYear() + 1, 0, 1);
        var elapse = Math.floor((end - start) / 1000);
        var seconds = elapse % 60 ;
        var minutes = Math.floor(elapse / 60) % 60;
        var hours = Math.floor(elapse / (60 * 60)) % 24;
        var days = Math.floor(elapse / (60 * 60 * 24)) % 30;
        var months = Math.floor(elapse / (60 * 60 * 24 * 30)) % 12;
        var years = Math.floor(elapse / (60 * 60 * 24 * 30 * 12));
        return start.getFullYear() + '年还剩' + years + '年' + months + '月' + days + '日'
            + hours + '小时' + minutes + '分' + seconds + '秒';
    }
    function domText(elem, text) {
        if (text == undefined) {
            if (elem.textContent) {
                return elem.textContent;
            } else if (elem.innerText) {
                return elem.innerText;
            }
        } else {
            if (elem.textContent) {
                elem.textContent = text;
            } else if (elem.innerText) {
                elem.innerText = text;
            } else {
                elem.innerHTML = text;
            }
        }
    }
    var target = document.getElementById('target');
    setInterval(function () {
        domText(target, getTimeString());
    }, 1000)
    </script>
  </body>
</html>
最后提交: 2/13/2023, 11:11:57 AM