vue3的一些知识点plus--4

2023-11-12

二十六,hooks使用

hooks,复用代码进行封装,钩子函数。和vue2中的mixins相似,将共同部分抽离出来。也有开源的库,vueUse,包含各种hooks,可以在 官网 查看。

我们自己怎么编写呢,要知道hook底层就是个函数,返回promise方便我们后续then处理,函数里面就是具体功能的实现了,同时也有onMounted等生命周期处理不同钩子下的内容。

// 自定义hooks
import {onMounted} from 'vue'

type Options = {
  el:string
}

export default function(options:Options):Promise<{baseurl:string}>{
  return new Promise((resolve)=>{
    onMounted(()=>{
      let img:HTMLImageElement = document.querySelector(options.el) as HTMLImageElement
      img.onload = ()=>{
        resolve({
          baseurl:base64(img)
        })
      }
    })

    const base64 = (el:HTMLImageElement)=>{
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')
      canvas.width = el.width
      canvas.height = el.height
      //参数:使用的图像,剪切x,剪切y,图像宽,图像高,画布x,画布y,使用图像的宽,使用图像的高
      ctx?.drawImage(el,0,0,canvas.width,canvas.height)
      return canvas.toDataURL('image/jpeg')
    }
  })

}

我们编写一个图片转 base64 的 hook 叫 useBase64 ,然后的是一个promise函数,里面已经在onMounted中获取dom元素,然后canvas转换,返回结果;那在使用的时候就简单了。

import useBase64 from './index'

useBase64({
  el:'#img'
}).then((res)=>{
  console.log(res.baseurl);
})

二十七,全局变量和方法

全局的变量和方法,那就是在入口文件,main.ts中进行定义了,可以挂载到app(createApp)上,这样全局都可以访问到,之前全局定义的组件也是在main.ts中。

vue2中是,Vue.prototype.$xxx=xxx
在vue3中,对象有些不同,是在app.config.globalProperties上

// 定义全局变量和方法
app.config.globalProperties.$env = 'dev'
app.config.globalProperties.$filter = {
  format<T>(str:T){
    return 'myfilter-'+str
  }
}
type Filter = {
  format<T>(str:T):string
}
// 对应是声明文件
declare module 'vue'{
  export interface ComponentCustomProperties{
    $filter:Filter,
    $env:string
  }
}

在使用中,template中可以直接进行使用,在script中需要通过实例获取得到。

// js
var app = getCurrentInstance()
console.log(app?.proxy?.$filter.format('好好'));

// html
<div>{{ $env }}</div>
<div>{{ $filter.format('111') }}</div>

二十八,样式框架使用 elplus

vue3 支持新版样式框架,支持ts,这里介绍的是 element-plus。

安装,引入,use注册,然后使用,不多介绍;写法和按需引入官网都有。

import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
app.use(ElementPlus);

这里对scoped进行一个解释,html单页面,css需要进行模块化,避免样式错乱。
规则:

1,给html的dom节点加一个不重复的data属性,(data-v-123)来表示唯一性。

2,在每句css选择器末尾(生成之后的)加一个当前组件的data属性,来私有化。
3,如果组件内部包括其他组件,只会给其他组件的最外层加上当前的data属性。

有时候 2,3 会冲突,因为data属性是加在末尾的,组件里面的层次没有data属性,无法命中,所以提供了一个样式穿透vue2--> /deep/   vue3--> :deep(选择器)

 源码里,scoped是通过postCss中的一个插件来处理的,接收一个css文件和一个api来分析,修改它的规则(css抽象树的方式),跟babel类似。
还有 :slotted() 插槽,:global() 全局 , v-bind() 动态修改css 的用法。

1,:slotted(选择器),处理插槽中的样式。

// html
<slot></slot>

// css
:slotted(.a) {
  color: red;
}

2,:global(选择器) ,处理全局的样式

:global(div) {
  background-color: antiquewhite;
}

 3,v-bind(),参数如果是值,直接使用;如果是对象,需要引号包裹

// js
let style1 = ref('blue')
let style = ref({
  color: "pink",
});

// css
.dym {
  background-color : v-bind(style1); /* 如果是值,直接使用 */
  color: v-bind("style.color"); /* 如果是对象,使用引号包裹 */
}

也可以使用 module 模块化的形式,类似于react。给style定义module名称,然后对象形式访问。
css module 使用,默认叫$style ,可以自定义名字,使用名字.

// html
<div :class="[mName.dym2, mName.border]">
  css module 使用,默认叫$style ,可以自定义名字,使用名字
</div>

<style module="mName">
.dym2 {
  color: blueviolet;
}
.border {
  border: 1px solid #2cc;
}
</style>

这里介绍一个库 tailwindcss,js编写css, postcss解析,更加的快捷,不过打包编译时间也会增加。

二十九,编写全局插件,app.use() 注册

定义一个loading组件,通过封装为一个插件,可以在全局注册使用。要知道,能够被app.use()注册的应该具有什么,首先导出一个对象,也可以是个函数,必须具有install()的方法,因为app.use()就是会调用函数或者对象里的install来实现注册。

需要将loading组件引入,然后使用 createVNode(loading)来生成vNode类型,抽象元素,然后render(VNode,document.body)挂载在body下,最后,app.config.globalProperties 上挂载,vNode.component?.exposed?.xxx 可以得到exposed暴露出来的属性方法。install会返回app参数,main.ts中的app。

// 可以导出一个对象,也可以是函数
// 通过在main.ts中使用 app.use()进行注册

import type { App, VNode } from "vue";
import loading from "./index.vue";
import { createVNode, render } from "vue";

// 1,对象里必须有install,会进行调用
export default {
  // install 会回传一个app函数,(main.ts中的全局app)
  install(app: App) {
    // 需要将 组件 挂载到全局,vNode类型
    const vNode: VNode = createVNode(loading);
    // 挂载 render 函数 (vnode,挂载点)
    render(vNode, document.body);
    // 可以获取到 component 的方法
    // vNode.component.setupState 可以获得到所有的函数,最好使用 exposed 访问暴露出的方法

    // 可以全局挂载
    app.config.globalProperties._loading = {
      show: vNode.component?.exposed?.show,
      hide: vNode.component?.exposed?.hide,
    };

    console.log(vNode, vNode.component?.exposed);
  },
};

然后 main.ts 中引入loading,app.use(loading)注册。用以下方法就可以使用了。

var instance = getCurrentInstance()
instance?.proxy?._loading.show()
setTimeout(() => {
  instance?.proxy?._loading.hide()
}, 3000);

三十,nextTick的使用

知识准备:

event loop,js是单线程,不然同时操作dom会出现问题。h5中的web workder支持多线程,也不能操作dom,一般是将费时的任务分出去,优化体验。
js 因为单线程,会出现很多排队,会等待很久,所以出现了异步。

同步:代码从上到下按顺序执行。
异步:分为宏任务和微任务。
           宏任务:script,setTimeout,setInterval,ui交互,postMessage,Ajax
           微任务:promise then catch finally,mutationObserver(监听dom变化),process.nextTick(nodejs环境),await。

同步任务在主进程形成一个执行栈,除此之外,还有一个任务队列。异步任务先执行宏任务,然后清空当次宏任务的所有微任务。 
nextTick 就是创建下一个异步任务,等到同步任务执行完毕后执行。

我们先来看个例子,看和输出结果一样吗:

async function Prom() {
  console.log("X");
  await Promise.resolve(); // 微任务
  console.log("Y");
}

setTimeout(() => {
  console.log(1);
  Promise.resolve().then(() => {
    console.log(2);
  });
}, 0);

setTimeout(() => {
  console.log(3);
  Promise.resolve().then(() => {
    console.log(4);
  });
}, 0);

Promise.resolve().then(() => {
  console.log(5);
});
Promise.resolve().then(() => {
  console.log(6);
});
Promise.resolve().then(() => {
  console.log(7);
});
Promise.resolve().then(() => {
  console.log(8);
});

Prom();
console.log(0);


// 执行结果: X 0 5 6 7 8 Y 1 2 3 4

nextTick() 的执行原理就是 flushJobs() 函数。
执行watch的对应队列,flush:pre的,顺序队列,父级在子级前创建,然后执行flush:post的回调。
永远返回promise,微任务,所以会先走上面的任务,然后走微任务,nextTick。

const change = async () => {
  message.value = "小小";
  console.log(div.value?.innerText, "同步情况下打印的值并没有改变");  // 原始
  await nextTick();
  console.log(div.value?.innerText, "异步情况下打印的值改变了");  // 小小
  for (let i = 0; i < 5; i++) {
    num.value = i;
  }

  for (var i = 0; i < 5; i++) {
    setTimeout(() => {
      console.log(i);
    }, 0);
  }
  // 5 5 5 5 5
};

三十一,unocss 原子化css ☆

unocss,目的是实现原子化css,可以在html中直接写css内容,动态根据你的规则生成对应的css,可以简化css的编写,也可以在熟练后更清晰的查看html。我形容的是我的理解,更深入的了解请到官网。

安装unocss,然后在 vite.config.ts 中引入注册。这里可以配置一些预设,也可以根据规则自定义

  • presetIcons图标库,需要安装库@iconify-json (icones官网 https://icones.js.org/ 找一套)
  • presetAttributify这个预设,就可以直接在标签上使用 属性 方式。
  • presetUno 工具类,可以直接使用,比如tailwind里的属性。
import unoCss from 'unocss/vite'

plugins: [
    unoCss({
      // 预设
      /* presetIcons图标库,需要安装库@iconify-json (icones官网 https://icones.js.org/ 找一套)
         presetAttributify这个预设,就可以直接在标签上使用 属性 方式。
         presetUno 工具类,可以直接使用,比如tailwind里的属性。
      */
      presets:[presetIcons(),presetAttributify(),presetUno()],
      rules:[
        ['flex',{display:'flex'}],
        ['red',{color:'red'}],
        [/^m-(\d+)$/,([,d])=>({margin:`${Number(d)*10}px`})]
      ],
      shortcuts:{
        cike:['flex','red','m-3']
      }
    })
  ],

然后使用的方法,可以是class,也可以是属性形式,还可以使用一些内设好的样式。

  <div class="flex red m-1">刺客</div>
  <div class="cike">刺客2</div>
  <div m="2" red>刺客3</div>
  <div class="bg-red-100">tailwind</div>
  图标使用:
  <div class="i-ic-baseline-add-shopping-cart"></div>

现阶段还是试验阶段,是否可以使用到团队里,进行规则的规范也很重要,可以多了解一些tailwind和unocss的关系。

 三十二,h函数

h函数,是vue中插件虚拟节点的辅助函数。接收三个参数,标签名,属性对象,子节点
这里和 createVNode() 方法一样的,render进行渲染。

  <btn @on-click="getBtn">
    <template #default>232</template>
  </btn>


// h 函数
type Props = {
  text?: string;
};

const btn = (props: Props, ctx: any) => {
  return h(
    "div",
    {
      class: ["rounded", "bg-green-400", "text-gray-50", "text-center", "p-2"],
      onClick: () => {
        ctx.emit("on-click", "按钮click");
      },
    },
    // props.text
    ctx.slots.default()
  );
};
var getBtn = (str: string) => {
  console.log(str);
};

三十三,了解use函数基础的实现

之前的例子里,写了一个loading插件,通过app.use()来注册的,那我们来了解一下use的基础实现

要知道,之前强调一定要有install函数,接收的参数是 插件和options配置

import type {App} from 'vue'
// 引入 app
import {app} from './main'

// 对 泛型T 做个约束,必须有install函数
interface Use{
  install:(app:App,...options:any[])=>void
}

// 进行缓存,避免重复的添加
const installList = new Set()

export function MyUse<T extends Use>(plugin:T,...options:any[]){

  if(installList.has(plugin)){
    console.error('已经注册',plugin);
  }else{
    plugin.install(app,...options)
    installList.add(plugin)
  }

  // 这里可以进行链式调用。
  return app

}

通过一个set来管理插件,避免重复,如果重复,给出提示;如果没有重复,执行插件的install方法,然后加入到set里,最后,返回app,可以支持链式调用。类似于app.use(A).use(B)的用法也是很常见的。

import { MyUse } from "./myUse";

MyUse(Loading)

这样测试也是可以实现loading的使用的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

vue3的一些知识点plus--4 的相关文章

随机推荐

  • 微信小程序静态初步

    社团微信小程序 1 由于兴趣驱动 一直在学习微信小程序 由于之前一直学习Java 但是大三第一学期即将结尾 所以为了能让下学期的学习减少工作量所以就打算利用闲散时间开发小程序 于是就拿社团为例子 自己一步步摸索 现在只是初步学习 所以这些天
  • mysql-Innodb事务隔离级别-repeatable read详解(转)

    mysql Innodb事务隔离级别 repeatable read详解 转 一 事务隔离级别 ANSI ISO SQL标准定义了4中事务隔离级别 未提交读 read uncommitted 提交读 read committed 重复读 r
  • vim配置经典

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 在终端 输入以下命令来编辑vimrc配置文件 sudo vim etc vim vimrc 或者 sudo gedit etc vim vimrc 将其复制粘贴进去 Des
  • GeoDa:入门基础

    前言 GeoDa是一个免费的开源软件工具 用于空间数据分析 它旨在通过探索和建模空间模式来促进数据分析的新见解 GeoDa是由Luc Anselin博士和他的团队开发的 该项目为探索性空间数据分析 ESDA 方法提供了用户友好的图形界面 例
  • mysql中join源码分析,MySQL中Join算法实现原理分析[图]

    在MySQL 中 只有一种 Join 算法 就是大名鼎鼎的 Nested Loop Join 他没有其他很多数据库所提供的 Hash Join 也没有 Sort Merge Join 顾名思义 Nested Loop Join 实际上就是通
  • 把二叉树转换成树(代码实现)

    前言 相信大家都知道二叉树如何转化成树 但是让你用代码实现 却发现自己无从下手 下面我将用代码实现 思想 树用二叉树来存储的话 那么类型是 左儿子 右兄弟 即二叉树某节点和它的左儿子在树中的关系也是父子关系 而与右儿子在树中的关系是兄弟关系
  • 机器视觉中非常好的github仓库

    AwesomeComputerVision Multi Object Tracking Paper List https github com SpyderXu multi object tracking paper list awesom
  • Oracle VM VirtualBox 不显示64位系统 linux 64 redhat 64

    打开BIOS里的虚拟化技术 修改bios中的virtualization 设为ENABLED
  • Elasticsearch 基本使用(三)条件查询

    条件查询 简单查询 term terms range match debug 查看分词结果 match phrase match phrase prefix match bool prefix multi match 复合查询 bool 查
  • 【c++之于c的优化 - 下】

    前言 一 inline 概念 以inline修饰的函数叫做内联函数 编译时C 编译器会在调用内联函数的地方展开 没有函数调用建立栈帧的开销 内联函数提升程序运行的效率 如果在上述函数前增加inline关键字将其改成内联函数 在编译期间编译器
  • 获取outputstream大小_关于inputStream.available()方法获取下载文件的总大小

    如果用inputStream对象的available 方法获取流中可读取的数据大小 通常我们调用这个函数是在下载文件或者对文件进行其他处理时获取文件的总大小 以前在我们初学File和inputStream和outputStream时 有需要
  • C++标准库之中文输出详细介绍【转】

    iostream printf wprintf和中文输出 本文引用出处 http www enjoysoft cn blog post 62 html使用C 标准库的iostream 可以方便地将控制台 文件 字符串以及其它可扩充的外部表示
  • Vue使用v-for遍历map

    功能 遍历数据库中按钮的图片和名字 当页面打开时 触发查询事件 以下图形式显示出来 前端代码 遍历存在数据库中的按钮名称和图片名称 其中按钮的click事件名称和按钮图片名称相同
  • Linux命令 理解

    RPM常用命令参数列表 1 安装一个包 rpm ivh 2 升级一个包 rpm Uvh 注意U一定要大写 i 安装 U 升线安装 h 以 显示安装进度 v 显示附加信息 3 移走一个包 rpm e 4 安装参数 force 即使覆盖属于其它
  • 变透明的黑匣子:UCLA 开发可解释神经网络 SNN 预测山体滑坡

    内容一览 由于涉及到多种时空变化因素 山体滑坡预测一直以来都非常困难 深度神经网络 DNN 可以提高预测准确性 但其本身并不具备可解释性 本文中 UCLA 研究人员引入了 SNN SNN 具有完全可解释性 高准确性 高泛化能力和低模型复杂度
  • 基本的信号——矩阵脉冲信号(门函数)

    门函数的数学表达式为 example1 矩形脉冲信号的matlab代码如下 矩形脉冲信号 clc clear close all t 0 0 001 4 T 1 ft rectpuls t 2 T 2 T plot t ft 运行结果如下
  • Normalize 和 normalized

    首先说明下 normalized的是vector的属性 而Normalize 是vector的方法 normalized和Normalize 都是可读的 读到的值是单位向量的值 只是nomalized不会更改当前vector本身的值 只是返
  • [转载]PropertyChanged 事件

    在 NET平台上 数据绑定是一项令人十分愉快的技术 利用数据绑定能减少代码 简化控制逻辑 通常 可以将某个对象的一个属性绑定到一个可视化的控件上 当属性值改变时 控件上的显示数据也随之发生变化 要实现这一功能 只需要为自定义对象实现 INo
  • Pandas 笔记 (一)

    Pandas 笔记 Pandas 提供高性能 易于使用的数据结构和数据分析工具 Pandas 可以从 CSV JSON SQL MICROSOFTEXCEL 导入数据 Pandas 可以对各种数据进行运算操作 比如归并 再形成 选择 还有数
  • vue3的一些知识点plus--4

    二十六 hooks使用 hooks 复用代码进行封装 钩子函数 和vue2中的mixins相似 将共同部分抽离出来 也有开源的库 vueUse 包含各种hooks 可以在 官网 查看 我们自己怎么编写呢 要知道hook底层就是个函数 返回p