vue3.0 搭建项目总结(详细步骤)


Posted in Javascript onMay 20, 2019

1.环境配置

项目中的不同开发环境有很多依赖配置,所以可以根据环境设置不同的配置,以免在不同环境经常修改文件

1 在根目录下创建 `.env.[环境]` 文件,可以在不同环境设置一些配置变量,如图

vue3.0 搭建项目总结(详细步骤)

vue3.0 搭建项目总结(详细步骤) 

.env.dev 文件

2.eslint 配置

在package.json 文件里面有一个eslintConfig对象,可设置rules: 如图

vue3.0 搭建项目总结(详细步骤)

3.配置svg

在vue.config.js 里面需在module.exports对象里面设置

chainWebpack: config => {
  config.module.rules.delete('svg') // 重点:删除默认配置中处理svg,//const svgRule = config.module.rule('svg') //svgRule.uses.clear()
  config.module
   .rule('svg-sprite-loader')
   .test(/\.svg$/)
   .use('svg-sprite-loader')
   .loader('svg-sprite-loader')
   .options({
    symbolId: 'icon-[name]'
   })
 }

svg component

<template>
 <svg :class="svgClass" aria-hidden="true">
  <use :xlink:href="iconName" rel="external nofollow" />
 </svg>
</template>

<script>
export default {
 name: 'SvgIcon',
 props: {
  iconClass: {
   type: String,
   required: true
  },
  className: {
   type: String,
   default: ''
  }
 },
 computed: {
  iconName() {
   return `#icon-${this.iconClass}`
  },
  svgClass() {
   if (this.className) {
    return 'svg-icon ' + this.className
   } else {
    return 'svg-icon'
   }
  }
 }
}
</script>

<style scoped>
.svg-icon {
 width: 1em;
 height: 1em;
 vertical-align: -0.15em;
 fill: currentColor;
 overflow: hidden;
}
</style>

```

使用svg组件

import SvgIcon from '@/components/SvgIcon.vue'
// 设置全局组件svgIcon
Vue.component('svg-icon', SvgIcon)
const req = require.context('./assets/svg', true, /\.svg$/) // 查询文件加下面的svg文件
const requireAll = requireContext => requireContext.keys().map(requireContext)
requireAll(req) // 全局导入svg文件

2.通用组件

级联(多选且可以选择全部)组件

安装插件 multi-cascader-base-ele

使用

import multiCascader from 'multi-cascader-base-ele'
Vue.use(multiCascader)

-- 支持选择全部

<template>
 <div>
  <MultiTestCascader v-model="selectedOptions" class="multi-cascader" :props="customProps" :options="options" multiple filterable select-children :show-all-levels="false" clearable only-out-put-leaf-node @change="cascaderChange" />
 </div>
</template>
<script>
export default {
 props: {
 // 传入级联列表数据
  options: {
   type: Array,
   default: () => []
  },
  // 传入选择数据
  list: {
   type: Array,
   default: () => []
  },
  // 自定义相关字段
  customProps: {
   type: Object,
   default: () => {
    return {
     label: 'label',
     value: 'value',
     children: 'children'
    }
   }
  },
  // 显示全部类型 1 全部二级/全部三级 2 全部二级分类/全部三级分类 3 全省/全市
  type: {
   type: String,
   default: () => '1'
  }
 },
 data() {
  return {
   selectedOptions: this.list,
   listStatus: true
  }
 },
 created() {

 },
 watch: {
  options(newValue, oldValue) {
   this.setListDisabled(newValue)
   this.addAllLabel(newValue)
  },
  list(newValue) {
   if (this.listStatus) {
    this.cascaderChange(newValue)
    this.listStatus = false
   }
  }
 },
 mounted() {
  this.setListDisabled(this.options)
  this.addAllLabel(this.options)
 },
 methods: {
  addAllLabel(list) {
   list.forEach(val => {
    if (val[this.customProps.children] && val[this.customProps.children].length > 0 && val[this.customProps.children][0][this.customProps.label] !== (this.type === '1' ? '全部一级' : (this.type === '2' ? '全部一级分类' : (this.type === '3' ? '全省' : '')))) {
     if (val[this.customProps.children].length > 1) {
      val[this.customProps.children].unshift({
       [this.customProps.label]: this.type === '1' ? '全部二级' : (this.type === '2' ? '全部二级分类' : (this.type === '3' ? '全省' : '')),
       [this.customProps.value]: val[this.customProps.value],
       [this.customProps.children]: null
      })
     }
     val[this.customProps.children].forEach(v => {
      if (v[this.customProps.children] && v[this.customProps.children].length > 1 && v[this.customProps.children][0][this.customProps.label] !== (this.type === '1' ? '全部二级' : (this.type === '2' ? '全部二级分类' : (this.type === '3' ? '全省' : '')))) {
       if (v[this.customProps.children].length > 1) {
        v[this.customProps.children].unshift({
         [this.customProps.label]: this.type === '1' ? '全部三级' : (this.type === '2' ? '全部三级分类' : (this.type === '3' ? '全市' : '')),
         [this.customProps.value]: v[this.customProps.value],
         [this.customProps.children]: null
        })
       }
      }
     })
    }
   })
  },
  setListDisabled(list) {
   const label = this.customProps.label
   const value = this.customProps.value
   const children = this.customProps.children
   list.forEach(val => {
    val.disabled = false
    if (val[children]) this.setListDisabled(val[children])
   })
  },
  cascaderChange(itemList) {
   if (!itemList || itemList.length === 0) {
    this.selectedOptions = []
   }
   this.setListDisabled(this.options)
   const label = this.customProps.label
   const value = this.customProps.value
   const children = this.customProps.children
   this.options.forEach((v, l) => {
    this.selectedOptions.forEach(val => {
     if (val[0] === '-1') {
      if (v[value] !== '-1') v.disabled = true
      else v.disabled = false
      if (v[children] && v[children].length > 0) {
       v[children].forEach(c => { c.disabled = true })
      }
     } else {
      if (v[value] === '-1') v.disabled = true
      else v.disabled = false
      if (v[children] && v[children].length > 0) {
       v[children].forEach(c => { c.disabled = false })
      }
     }
     if (val.length === 2 && v[value] === val[0] && v[children]) {
      v[children].forEach((item, num) => {
       item.disabled = false
       if (val[0] === val[1] && item[value] === val[1]) {
        item.disabled = false
       } else {
        if (val[0] === val[1] && num !== 0) {
         item.disabled = true
         if (item[children]) {
          item[children].forEach(i => {
           i.disabled = true
          })
         }
        }
        if (val[0] !== val[1] && num === 0 && v[children].length > 1) item.disabled = true
       }
       // this.options[l][children][0].disabled = true
      })
     }
     if (val.length === 3 && v[value] === val[0] && v[children]) {
      v[children].forEach((item, j) => {
       // let status = false
       if (item[children] && val[1] === item[value]) {
        item.disabled = false
        item[children].forEach((i, index) => {
         i.disabled = false
         if (i[value] === val[2]) status = true
         if (i[value] === val[2] && val[1] === val[2]) {
          i.disabled = false
         } else {
          if (val[1] !== val[2] && index === 0 && v[children].length > 1) i.disabled = true
          if (val[1] === val[2] && index !== 0) i.disabled = true
         }
        })
        // this.options[0].disabled = true
        this.options[l][children][0].disabled = true
        // return status
       }
      })
     }
    })
   })
   this.selectedOptions = this.selectedOptions.map(val => {
    if (val.length === 2 && val[0] === val[1]) return [val[0]]
    if (val.length === 1 && val[0] === '-1') return [val[0]]
    if (val.length === 3 && val[1] === val[2]) return [val[0], val[1]]
    return val
   })
   const item = this.selectedOptions[this.selectedOptions.length - 1]
   const length = this.selectedOptions.length
   let status = -1
   this.selectedOptions.some((val, index) => {
    if ((length - 1) === index) return true
    if (item.length === val.length) {
     if (item.join(',') === val.join(',')) {
      status = 1
      return true
     }
    }
    if (item.length > val.length) {
     if (item.join(',').includes(val.join(','))) {
      status = 2
      return true
     }
    }
    if (val.length > item.length) {
     if (val.join(',').includes(item.join(','))) {
      status = 3
      return true
     }
    }
   })
   if (status !== -1) {
    this.selectedOptions.splice(this.selectedOptions.length - 1, 1)
   }
   this.$emit('update:list', this.selectedOptions)
  }
 }
}
</script>

上传(支持图片/视频/裁剪图片/拖拽)

安装插件

vuedraggable axios vue-cropper

代码

<!-- -->
<template>
 <div class="image-draggable">
  <draggable v-model="draggableList" @end="onEnd">
   <!-- <transition-group> -->
   <div v-for="(item, index) in draggableList" :key="index" class="image-list">
    <template v-if="item.isImg">
     <img :src="item.displayUrl" alt="" srcset="" style="width: 148px; height: 148px;">
     <div class="icon">
      <span @click="viewImage(item.displayUrl)">
       <svg-icon icon-class="view" class="icon-size" style="margin-right: 10px;"></svg-icon>
      </span>
      <span @click="remove(index)">
       <svg-icon icon-class="delete" class="icon-size"></svg-icon>
      </span>
     </div>
    </template>
    <template v-if="!item.isImg">
     <video :src="item.displayUrl" :ref="item.id" :id="item.id" :poster="item.coverUrl" style="width: 148px; height: 148px;">
     </video>
     <div class="icon">
      <span v-if="item.isPlay" @click="play(item)" class="video-icon">
       <svg-icon icon-class="play" class="icon-size"></svg-icon>
      </span>
      <span v-if="!item.isPlay" @click="pause(item)" class="video-icon">
       <svg-icon icon-class="pause" class="icon-size"></svg-icon>
      </span>
      <span @click="fullPlay(item)" class="video-icon">
       <svg-icon icon-class="full" class="icon-size"></svg-icon>
      </span>
      <span @click="remove(index)">
       <svg-icon icon-class="delete" class="icon-size"></svg-icon>
      </span>
     </div>
    </template>
   </div>

   <!-- </transition-group> -->
  </draggable>
  <el-upload :id="uploadId" :disabled="isDiabled" :action="uploadUrl" class="image-upload" :headers="headers" :accept="accept" list-type="picture-card" :show-file-list="false" :on-preview="handlePictureCardPreview" :on-progress="handleProgress" :on-change="fileChange" :auto-upload="!isCropper" :on-remove="handleRemove" :on-success="imageSuccess" :before-upload="fileBeforeUpload">
   <i class="el-icon-plus"></i>
   <el-progress :percentage="percentage" v-if="isUpload && isLoading" :show-text="false"></el-progress>
  </el-upload>
  <el-dialog :visible.sync="dialogVisible">
   <img width="100%" :src="dialogImageUrl" alt="">
  </el-dialog>
  <el-dialog :visible.sync="modifyCropper">
   <div :style="{height: (autoCropHeight + 100) + 'px'}">
    <vueCropper ref="cropper" :img="imgSrc" :outputSize="option.size" :outputType="option.outputType" :info="true" :full="option.full" :canMove="option.canMove" :canMoveBox="option.canMoveBox" :original="option.original" :autoCrop="option.autoCrop" :autoCropHeight="autoCropHeight" :autoCropWidth="autoCropWidth" :fixedBox="option.fixedBox" @realTime="realTime" @imgLoad="imgLoad"></vueCropper>
   </div>
   <span slot="footer" class="dialog-footer">
    <el-button @click="modifyCropper = false">取 消</el-button>
    <el-button type="primary" @click="uploadCropperImage">确 定</el-button>
   </span>
  </el-dialog>
 </div>
</template>

<script>
// 拖拽
import draggable from 'vuedraggable'
// 裁剪
import { VueCropper } from 'vue-cropper'
// 上传地址
import { upload } from '@/api'
import { getToken } from '@/util/auth'
import axios from 'axios'

export default {
 name: '',
 data() {
  return {
   headers: {
    Authorization: getToken()
   },
   uploadUrl: upload,
   displayUrl: '',
   dialogImageUrl: '',
   dialogVisible: false,
   percentage: 0,
   accept: '',
   draggableList: [],
   isUpload: false,
   modifyCropper: false,
   isDiabled: false,
   cropperImage: {
   },
   uploadId: 'id' + Date.now(),
   imgSrc: '',
   option: {
    size: 0.5,
    full: true, // 输出原图比例截图 props名full
    outputType: 'png',
    canMove: true,
    original: true,
    canMoveBox: false,
    autoCrop: true,
    fixedBox: true
   }
  }
 },
 props: {
  // 已存在的文件
  fileList: {
   type: Array,
   default() {
    return [
    ]
   }
  },
  // 返回类型 Array 数组 Object 对象
  returnType: {
   type: String,
   default: 'Array'
  },
  // 自定义对象
  customObject: {
   type: Object,
   default: () => { }
  },
  // 上传的最大个数
  maxNum: {
   type: Number,
   required: true,
   default: 1
  },
  // 单位MB
  maxSize: {
   type: Number,
   default: 15
  },
  autoCropWidth: {
   type: Number,
   default: 180
  },
  autoCropHeight: {
   type: Number,
   default: 180
  },
  // 上传类型 All 图片/视频 image 图片 video视频
  acceptType: {
   type: String,
   default: 'All'
  },
  // 是否裁剪
  isCropper: {
   type: Boolean,
   default: false
  },
  // 是否显示加载条
  isLoading: {
   type: Boolean,
   default: true
  },

  outputSize: {
   type: Number,
   default: 1
  },
  outputType: {
   type: String,
   default: 'jpeg'
  }
 },
 components: {
  draggable,
  VueCropper
 },
 watch: {
  draggableList(newValue, oldValue) {
   this.getElement(this.draggableList.length)
  },
  fileList(newValue, oldValue) {
   this.draggableList = newValue
   this.initImage()
  }
 },

 computed: {},

 mounted() {
  if (this.acceptType === 'All') {
   this.accept = 'image/png, image/jpeg, image/gif, image/jpg, .mp4,.qlv,.qsv,.ogg,.flv,.avi,.wmv,.rmvb'
  }
  if (this.acceptType === 'image') {
   this.accept = 'image/png, image/jpeg, image/gif, image/jpg'
  }
  if (this.acceptType === 'video') {
   this.accept = '.mp4,.qlv,.qsv,.ogg,.flv,.avi,.wmv,.rmvb'
  }
  this.initImage()
 },
 methods: {
  // 获取五位数的随机数
  getRandom() {
   return (((Math.random() + Math.random()) * 10000) + '').substr(0, 5).replace('.', 0)
  },
  initImage() {
   const _this = this
   // console.log('file', this.fileList)
   if (this.fileList.length > 0) {
    this.draggableList = this.fileList.map(val => {
     let displayUrl = ''
     let coverUrl = ''
     let isImg = true
     const files = (val.url ? val.url : val).split(',')
     if (files.length === 3) {
      displayUrl = files[1]
      coverUrl = files[2]
      isImg = false
     } else if (files.length === 1) {
      displayUrl = (val.url ? val.url : val)
      isImg = true
     }
     const fileObj = Object.assign({}, {
      coverUrl: coverUrl,
      displayUrl: displayUrl,
      isImg: isImg,
      isPlay: true,
      name: Date.now(),
      url: (val.url ? val.url : val),
      id: val.id || Date.now() + _this.getRandom()
     })
     return fileObj
    }).filter(val => { return val.url })
   }
  },
  handleRemove(file, fileList) {
   this.getElement(fileList.length)
  },
  handlePictureCardPreview(file) {
   this.dialogImageUrl = file.url
   this.dialogVisible = true
  },
  handleProgress(event, file, fileList) {
   this.percentage = +file.percentage
  },
  fileBeforeUpload(file, event) {
   if (this.acceptType === 'image' && !file.type.includes('image/')) {
    this.$warning('请上传图片')
    return false
   }
   if (this.acceptType === 'video' && !file.type.includes('video/')) {
    this.$warning('请上传视频')
    return false
   }
   this.isUpload = true
   if (file.type.includes('image/') && (file.size > this.maxSize * 1024 * 1024)) {
    this.$warning(`请上传小于${this.maxSize}M的图片`)
    this.percentage = 0
    this.isLoading = false
    return false
   }
   if (file.type.includes('video/')) this.isDiabled = true
   if (this.isCropper) {
    return false
   }
  },
  fileChange(file, fileList) {
   if (file.percentage === 0 && this.isCropper) {
    if (file.raw.type.includes('video/')) {
     this.$warning('请上传图片')
     return
    }
    this.imgSrc = file.url
    this.modifyCropper = true
    this.cropperImage = {
     coverUrl: '',
     isImg: true,
     isPlay: true,
     name: file.name
    }
   }
  },
  // 实时预览函数
  realTime(data) {
   this.previews = data
  },
  imgLoad(data) {
  },
  // 裁剪后上传图片
  uploadCropperImage() {
   const _this = this
   this.$refs.cropper.getCropBlob((data) => {
    const config = {
     headers: {
      'Authorization': _this.headers.Authorization,
      'Content-Type': 'multipart/form-data'
     }
    }
    const formdata = new FormData()
    formdata.append('file', data)
    // this.uploadUrl 上传
    axios.post(this.uploadUrl, formdata, config).then(response => {
     _this.cropperImage = Object.assign({}, _this.cropperImage, {
      displayUrl: response.data.data,
      url: response.data.data,
      id: Date.now()
     })
     _this.draggableList.push(_this.cropperImage)
     _this.$emit('getImageList', _this.draggableList.map(val => {
      if (this.returnType === 'Array') {
       return val.url
      }
      if (this.returnType === 'Object') {
       return {
        url: val.url,
        uploadStatus: true
       }
      }
     }), _this.customObject)
     _this.modifyCropper = false
    }).catch(error => {
     console.log('err', error)
    })
   })
  },
  imageSuccess(response, file, fileList) {
   const _this = this
   try {
    this.getElement(fileList.length)
    let displayUrl = ''
    let coverUrl = ''
    let isImg = true
    const url = file.response.data || file.url
    this.isUpload = false
    const files = url.split(',')
    if (files.length === 3) {
     displayUrl = files[1]
     coverUrl = files[2]
     isImg = false
    } else if (files.length === 1) {
     displayUrl = url
     isImg = true
    }
    const id = Date.now()
    _this.draggableList.push({
     name: file.name,
     url: url,
     coverUrl: coverUrl,
     displayUrl: displayUrl,
     isImg: isImg,
     isPlay: true,
     id: id
    })
    if (isImg) {
     _this.percentage = 0
     _this.$emit('getImageList', _this.draggableList.map(val => {
      if (this.returnType === 'Array') {
       return val.url
      }
      if (this.returnType === 'Object') {
       return {
        url: val.url,
        uploadStatus: true
       }
      }
     }), _this.customObject)
     return
    }
    _this.$emit('getImageList', _this.draggableList.map(val => {
     if (this.returnType === 'Array') {
      return val.url
     }
     if (this.returnType === 'Object') {
      return {
       url: val.url,
       uploadStatus: false
      }
     }
    }), _this.customObject)
    setTimeout(() => {
     const keys = Object.keys(_this.$refs)
     const video = _this.$refs[`${keys[keys.length - 1]}`][0]
     const removeId = keys[keys.length - 1]
     const interval = setInterval(() => {
      if (video.readyState === 4) {
       const duration = video.duration
       this.isDiabled = false
       if (duration < 3 || duration > 60) {
        _this.$message.success('请上传大于三秒小于六十秒的视频')
        _this.percentage = 0
        // _this.remove(_this.draggableList.length - 1)
        _this.draggableList = _this.draggableList.filter(val => {
         return (val.id + '') !== (removeId + '')
        })
        _this.$emit('getImageList', _this.draggableList.map(val => {
         if (this.returnType === 'Array') {
          return val.url
         }
         if (this.returnType === 'Object') {
          return {
           url: val.url,
           uploadStatus: true
          }
         }
        }), _this.customObject)
        _this.getElement(_this.draggableList.length)
       }
       _this.percentage = 0
       _this.$emit('getImageList', _this.draggableList.map(val => {
        if (this.returnType === 'Array') {
         return val.url
        }
        if (this.returnType === 'Object') {
         return {
          url: val.url,
          uploadStatus: true
         }
        }
       }), _this.customObject)
       clearInterval(interval)
      }
      video.src = displayUrl
      video.poster = coverUrl
     }, 1000)
    }, 1000)
   } catch (error) {
    console.log('error', error)
   }
  },
  play(item) {
   const video = document.getElementById(item.id)
   video.play()
   item.isPlay = !item.isPlay
  },
  pause(item) {
   const video = document.getElementById(item.id)
   video.pause()
   item.isPlay = !item.isPlay
  },
  // 全屏播放
  fullPlay(item) {
   const video = document.getElementById(item.id)
   // w3c
   typeof video.requestFullScreen === 'function' && video.requestFullScreen()
   // webkit(谷歌)
   typeof video.webkitRequestFullScreen === 'function' && video.webkitRequestFullScreen()
   // 火狐
   typeof video.mozRequestFullScreen === 'function' && video.mozRequestFullScreen()
   // IE
   typeof video.msExitFullscreen === 'function' && video.msExitFullscreen()
  },
  viewImage(url) {
   this.dialogImageUrl = url
   this.dialogVisible = true
  },
  remove(index) {
   this.draggableList.splice(index, 1)
   this.$emit('getImageList', this.draggableList.map(val => {
    if (this.returnType === 'Array') {
     return val.url
    }
    if (this.returnType === 'Object') {
     return {
      url: val.url,
      uploadStatus: true
     }
    }
   }), this.customObject)
   this.getElement(this.draggableList.length)
  },
  onEnd(event) {
   this.$emit('getImageList', this.draggableList.map(val => {
    if (this.returnType === 'Array') {
     return val.url
    }
    if (this.returnType === 'Object') {
     return {
      url: val.url,
      uploadStatus: true
     }
    }
   }), this.customObject)
  },
  isImg(obj) {
   const item = obj.url
   if (item === '' || item === null || typeof item === 'undefined') {
    return false
   }
   const index = item.lastIndexOf('.')
   var ext = item.substr(index + 1)
   if (ext.includes('!')) ext = ext.split('!')[0]
   ext = ext.toLowerCase()
   var tps = ['jpg', 'jpeg', 'png']
   let ok = false
   for (let i = 0; i < tps.length; i++) {
    if (tps[i] === ext) {
     ok = true
     break
    }
   }
   return ok
  },
  getElement(length) {
   const _this = this
   if (length >= _this.maxNum) {
    document.querySelectorAll(`#${_this.uploadId} .el-upload--picture-card`).forEach(val => {
     if (val.firstElementChild.className === 'el-icon-plus') {
      val.style.display = 'none'
      return true
     }
    })
   } else {
    document.querySelectorAll(`#${_this.uploadId} .el-upload--picture-card`).forEach(val => {
     if (val.firstElementChild.className === 'el-icon-plus') {
      val.style.display = 'inline-block'
      return true
     }
    })
   }
  }
 }
}

</script>
<style lang='scss' scoped>
.image-draggable {
  display: flex;
  flex-wrap: wrap;
  .image-list {
    position: relative;

    display: inline-block;
    overflow: hidden;

    width: 148px;
    height: 148px;
    margin-right: 10px;

    cursor: pointer;
    &:hover {
      .icon {
        height: 20%;

        transition: all .5s;
        .video-icon {
          display: inline-block;

          margin-right: 10px;
        }
      }
    }
    .icon {
      position: absolute;
      bottom: 0;

      display: flex;
      justify-content: center;

      width: 100%;
      height: 0;

      background-color: rgba(215, 215, 215, 1);
      .icon-size {
        width: 2em;
        height: 2em;
      }
      .video-icon {
        display: none;
      }
    }
  }
}
</style>
<style lang="scss">
.image-draggable {
  .el-progress {
    top: -50%;
  }
}
</style>

注册全局事件

创建eventBus.js

vue3.0 搭建项目总结(详细步骤)

使用

import eventBus from './plugins/eventBus'
Vue.use(eventBus)

处理缓存

借用mounted, activated 事件处理数据

在某一次打开页面的时候进行数据初始化存储, 放置在vuex中,或者全局变量中,当需要初始化进行一个初始化,采取mixins引入

vue3.0 搭建项目总结(详细步骤)

vue3.0 搭建项目总结(详细步骤)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js实现运动logo图片效果及运动元素对象sportBox使用方法
Dec 25 Javascript
jquery遍历select元素(实例讲解)
Dec 31 Javascript
JavaScript中Math对象方法使用概述
Jan 02 Javascript
禁止拷贝网页内容的js代码
Jan 22 Javascript
Backbone.js的Hello World程序实例
Jun 19 Javascript
jquery实现可横向和竖向展开的动态下滑菜单效果
Aug 24 Javascript
ECMA5数组的新增方法有哪些及forEach()模仿实现
Nov 03 Javascript
Javascript基于对象三大特性(封装性、继承性、多态性)
Jan 04 Javascript
基于JavaScript实现弹出框效果
Feb 19 Javascript
jquery操作checkbox火狐下第二次无法勾选的解决方法
Oct 10 Javascript
拖动时防止选中
Feb 03 Javascript
Vue实现Layui的集成方法步骤
Apr 10 Javascript
vue-cli webpack配置文件分析
May 20 #Javascript
微信小程序开发之左右分栏效果的实例代码
May 20 #Javascript
微信小程序rich-text富文本用法实例分析
May 20 #Javascript
bootstrap中的导航条实例代码详解
May 20 #Javascript
详解小程序云开发数据库
May 20 #Javascript
VUE脚手架具体使用方法
May 20 #Javascript
Vue CLI2升级至Vue CLI3的方法步骤
May 20 #Javascript
You might like
火车头采集器3.0采集图文教程
2007/03/17 PHP
php中删除字符串中最先出现某个字符的实现代码
2013/02/03 PHP
Ajax+PHP实现的分类列表框功能示例
2019/02/11 PHP
ExtJS4中使用mixins实现多继承示例
2013/12/03 Javascript
Jquery Ajax xmlhttp请求成功问题
2015/02/04 Javascript
JavaScript实现将数组中所有元素连接成一个字符串的方法
2015/04/06 Javascript
JavaScript必知必会(三) String .的方法来自何方
2016/06/08 Javascript
JS 通过系统时间限定动态添加 select option的实例代码
2016/06/09 Javascript
JSP基于Bootstrap分页显示实例解析
2016/06/12 Javascript
jquery之别踩白块游戏的简单实现
2016/07/25 Javascript
微信小程序 出现错误:{&quot;baseresponse&quot;:{&quot;errcode&quot;:-80002,&quot;errmsg&quot;:&quot;&quot;}}解决办法
2017/02/23 Javascript
jQuery实现的简单动态添加、删除表格功能示例
2017/09/21 jQuery
微信小程序实现底部导航
2018/11/05 Javascript
利用d3.js实现蜂巢图表带动画效果
2019/09/03 Javascript
Python实现对excel文件列表值进行统计的方法
2015/07/25 Python
Python的组合模式与责任链模式编程示例
2016/02/02 Python
Python中标准模块importlib详解
2017/04/16 Python
Python3中条件控制、循环与函数的简易教程
2017/11/21 Python
Python基于百度AI的文字识别的示例
2018/04/21 Python
python 实现登录网页的操作方法
2018/05/11 Python
python实现爬取图书封面
2018/07/05 Python
简单了解python变量的作用域
2019/07/30 Python
Django获取该数据的上一条和下一条方法
2019/08/12 Python
django中使用事务及接入支付宝支付功能
2019/09/15 Python
关于Python 常用获取元素 Driver 总结
2019/11/24 Python
pytorch方法测试——激活函数(ReLU)详解
2020/01/15 Python
Python中使用filter过滤列表的一个小技巧分享
2020/05/02 Python
Python中pass的作用与使用教程
2020/11/13 Python
英国最大的网上药品商店:Chemist Direct
2017/12/16 全球购物
初中英语教学反思
2014/01/25 职场文书
情人节活动策划方案
2014/02/27 职场文书
优秀求职信
2014/05/29 职场文书
代办出身证明书
2014/10/21 职场文书
优秀教师先进事迹材料
2014/12/15 职场文书
错误码NET::ERR_CERT_DATE_INVALID证书已过期解决方法?
2022/07/07 数码科技
react中useState使用:如何实现在当前表格直接更改数据
2022/08/05 Javascript