vue3一些笔记


ps:好久没更新了…还是要看看vue的文档更新一些内容啦

响应式api

vue3的响应式api真的太多了,就更新一些常用的吧

ref

//接受一个内部值,返回一个响应式的、可更改的 ref 对象
const count=ref<number>(0)
count.value+=1 //更改值

computed

//设置只读
 const user = ref([
      { id: 1, name: 'chen', age: 18 },
      { id: 2, name: 'wang', age: 19 },
      { id: 3, name: 'li', age: 24 },
    ])
 //返回年龄大于18的成员
const adultUser = computed(() => user.value.filter((item) => item.age > 18))
//可写计算属性

reactive

watchEffect

watch


状态管理

这么多东西我这么记得住?

pinia

vuex

状态管理对比

工具类

node_modules文件

删除文件: 
		该文件夹包含大量node安装包可以使用rimraf
		npm install rimraf -g
		rimraf node_modules  //删除该文件夹
安装文件:
		安装使用淘宝镜像:npm config set registry https://registry.npm.taobao.org
		查看淘宝镜像:npm config get registry
		安装文件:yarn install

案例篇

菜单

注:最好将菜单挂载到body,这样不会出现层级问题

html--
 <Card :status="status" :pX="pX" :pY="pY" :list="menuRef" />
  <nav>
    <li v-for="item in data" :key="item" @click.right="rightMenu($event, item)">
      {{ item }}
    </li>
  </nav>
  
js--
import { ref } from 'vue'
import Card from '@/components/Card/index.vue'
type MenuType = {
  label: String
  callback: () => void
}
const menuRef = ref<MenuType[]>()
const data = ref<number[]>([1, 2, 3, 4, 5, 6])
const status = ref<Boolean>(false)
const pX = ref<Number>(0)
const pY = ref<Number>(0)
const rightMenu = (event: any, id: number) => {
  const bodyWidth = document.body.clientWidth
  let mouseWidth = event.clientX
  if (bodyWidth - 200 < mouseWidth) {   //处理边界问题,右键不会移到窗口外面
    mouseWidth -= mouseWidth + 200 - bodyWidth
  }
  event.preventDefault()
  pX.value = mouseWidth
  pY.value = event.clientY
  status.value = true
  let menu = [
    {
      label: '删除',
      callback: () => {
        data.value = data.value.filter((item: number) => item !== id)
      },
    },
  ]
  menuRef.value = menu
}
window.addEventListener('click', () => {
  status.value = false
})


Card组件
<template>
  <nav
    class="page"
    ref="menuRef"
    :style="{ display: !status ? 'none' : '', left: pX + 'px', top: pY + 'px' }"
  >
    <li v-for="item in list" @click="item.callback()">
      {{ item.label }}
    </li>
  </nav>
</template>

<script lang="ts">
import { defineComponent, PropType, watch, ref } from 'vue'
type MenuType = {
  label: String
  callback: () => void
}
export default defineComponent({
  name: 'Card',
  props: {
    pX: {
      type: Number,
      default: 0,
    },
    pY: {
      type: Number,
      default: 0,
    },
    status: {
      type: Boolean,
      default: false,
    },
    list: {
      type: Array as PropType<MenuType[]>,
    },
  },
  emits: [],
  setup(props, { emit }) {
    const menuRef = ref<HTMLElement>()
    const body = document.querySelector('body')

    watch(
      () => props.status,
      (val) => {
        if (val && menuRef.value) {
          body?.appendChild(menuRef.value)
        } else if (menuRef.value) {
          body?.removeChild(menuRef.value)
        }
      }
    )
    return {}
  },
})
</script>

内容复制

  • read : 读取剪切板的内容;
  • readText: 读取剪切板文字内容;
  • write: 向剪切板中写入文字内容;
  • writeText: 向剪切板中写入内容;
<div class="copy" ref="copyRef">测试文字复制</div>

const copyRef = ref<HTMLDivElement>()
1--类似我们选中复制吧,会给文字添加一个背景,跟个智障一样
 function copyHandle() {
  if (!copyRef.value) return
   const range = document.createRange()
  range.selectNode(copyRef.value)
  const selection = window.getSelection()
  if (selection && selection.rangeCount > 0) selection?.removeAllRanges()
  selection?.addRange(range)
  const result = document.execCommand('copy')
  console.log(result)
}
2--Clipboard
不是Clipboard通过实例化创建对象,而是通过Navigator.clipboard全局访问系统剪贴板。

 使用 clipboard 的 writeText 方法实现复制
 	const value = copyRef.value.innerText
	const clipboardObj = navigator.clipboard
	await clipboardObj.writeText(value)
 使用 clipboard 的 write 方法实现复制
	async function copyHandle() {
	if (!copyRef.value) return
	const value = copyRef.value.innerText
	const clipboardObj = navigator.clipboard
	const type = 'text/plain'
	const blob = new Blob([value], { type })
	const data = [new ClipboardItem({ [type]: blob })]
	await clipboardObj.write(data)
}
 

验证码

<template>
  <div class="s-canvas">
    <canvas
      ref="canvasRef"
      class="canvas"
      @click="makeCode"
      :width="contentWidth"
      :height="contentHeight"
    ></canvas>
  </div>
</template>

<script lang="ts">
import { toRefs, onMounted, watch, defineComponent, ref, nextTick } from 'vue'
import { random } from 'lodash'

export default defineComponent({
  name: 'imageCode',
  props: {
    change: {
      // 刷新验证码使用
      type: Boolean,
      default: false,
    },
    contentWidth: {
      // 验证码图片宽
      type: Number,
      default: 112,
    },
    contentHeight: {
      // 验证码图片高
      type: Number,
      default: 38,
    },
  },
  emits: ['getCode'], // 返回验证码加密正确值的函数
  setup(props, { emit }) {
    const canvasRef = ref<HTMLCanvasElement>()
    // 默认值
    const defaultData = {
      identifyCode: '', // 验证码值,未加密的
      identifyCodes: '1234567890', // 生成验证码的元素,可以加入字母
      fontSizeMin: 20, // 图片上验证文字的最小值
      fontSizeMax: 40, // 图片上验证文字的最小值
      backgroundColorMin: 180, // 图片背景色值最小
      backgroundColorMax: 240, // 图片背景色值最大
      colorMin: 50, // 文字色值最小
      colorMax: 160, // 文字色值最大
      lineColorMin: 40, // 干扰线色值最小
      lineColorMax: 120, // 干扰线色值最大
      dotColorMin: 0, // 干扰点色值最小
      dotColorMax: 255, // 干扰点色值最大
      lineSum: 4, // 干扰线数量
      dotSum: 40, // 干扰点数量
    }
    // 父级传递
    const { contentWidth, contentHeight, change } = toRefs(props)
    // 生成一个随机的颜色
    const randomColor = (min: number, max: number) => {
      let r = random(min, max)
      let g = random(min, max)
      let b = random(min, max)
      return 'rgb(' + r + ',' + g + ',' + b + ')'
    }

    // 创建图形
    const drawPic = () => {
      // let canvas = document.getElementById('s-canvas')
      nextTick(() => {
        if (!canvasRef.value) return
        let ctx = canvasRef.value.getContext('2d')
        if (!ctx) return
        ctx.textBaseline = 'bottom'
        // 绘制背景
        ctx.fillStyle = randomColor(
          defaultData.backgroundColorMin,
          defaultData.backgroundColorMax
        )
        ctx.fillRect(0, 0, contentWidth.value, contentHeight.value)
        // 绘制文字
        for (let i = 0; i < defaultData.identifyCode.length; i++) {
          drawText(ctx, defaultData.identifyCode[i], i)
        }
        drawLine(ctx)
        drawDot(ctx)
      })
    }

    // 绘制文字
    const drawText = (
      ctx: CanvasRenderingContext2D,
      txt: string,
      i: number
    ) => {
      ctx.fillStyle = randomColor(defaultData.colorMin, defaultData.colorMax)
      ctx.font =
        random(defaultData.fontSizeMin, defaultData.fontSizeMax) + 'px SimHei'
      let x =
        (i + 1) * (contentWidth.value / (defaultData.identifyCode.length + 1))
      let y = random(defaultData.fontSizeMax, contentHeight.value)
      var deg = random(-30, 30)
      // 修改坐标原点和旋转角度
      ctx.translate(x, y)
      ctx.rotate((deg * Math.PI) / 180)
      ctx.fillText(txt, 0, 0)
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180)
      ctx.translate(-x, -y)
    }

    // 绘制干扰线
    const drawLine = (ctx: CanvasRenderingContext2D) => {
      for (let i = 0; i < 4; i++) {
        ctx.strokeStyle = randomColor(
          defaultData.lineColorMin,
          defaultData.lineColorMax
        )
        ctx.beginPath()
        ctx.moveTo(
          random(0, contentWidth.value),
          random(0, contentHeight.value)
        )
        ctx.lineTo(
          random(0, contentWidth.value),
          random(0, contentHeight.value)
        )
        ctx.stroke()
      }
    }
    // 绘制干扰点
    const drawDot = (ctx: CanvasRenderingContext2D) => {
      for (let i = 0; i < 60; i++) {
        ctx.fillStyle = randomColor(0, 255)
        ctx.beginPath()
        ctx.arc(
          random(0, contentWidth.value),
          random(0, contentHeight.value),
          1,
          0,
          2 * Math.PI
        )
        ctx.fill()
      }
    }

    // 生成图片
    const makeCode = () => {
      defaultData.identifyCode = ''
      for (let i = 0; i < 4; i++) {
        defaultData.identifyCode +=
          defaultData.identifyCodes[
            random(0, defaultData.identifyCodes.length - 1)
          ]
      }

      // 绘制图片
      drawPic()
      // 返回加密后的图片验证码值
      emit('getCode', defaultData.identifyCode)
    }

    // 初识函数,生成图片
    onMounted(() => {
      makeCode()
    })

    // 监听change变化,重新生成图片
    watch(change, () => {
      makeCode()
    })
    return {
      makeCode,
      canvasRef,
    }
  },
})
</script>

<style lang="scss" scoped>
.canvas {
  cursor: pointer;
}
</style>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值