01 自定义Hook
正常的组件:
<template>
<div>
<img id="img" src="./assets/images/01.png" width="300" height="300"></img>
</div>
</template>
<script>
// 导入hook组件 并传递一个参数
import userBase64 from './hooks'
userBase64({el:'#img'}).then(res=>{console.log(res,'base64图片的地址')})
</script>
Hook组件:
import {onMounted} from 'vue'
type Options = {el:string}
export default function (el:OPtions):Promise<{naseUrl:string}> {
return new Promise(resolve=>{
onMounted(()=>{
let img:HTMLImgElement = document.querySelector(options.el)
img.onload = ()=>{
resoleve({naseUrl:base64(img)})
}
})
const base64 = (el:HTMLImageElement)=>{
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
canvas.height = el.height
canvas.width = el.width
ctx?.drawImage(el,0,0,canvas.width,canvas.height)
return canvas.toDataURL('image/png')
}
})
}
02 实现一个函数同时支持hook和自定义指令,去监听DOM宽高的变化
// interSectionObserver 主要监听元素是否在视口内
// MutationObserver 主要监听子集的变化 属性的变化 以及增删改查
// ResizeObserver 主要监听元素宽高的变化
、、 创建hook函数
function useResize (el:HTMLElement,callback:Function){
let resize = new ResizeObserver((entries)=>{
console.log(entries) // 监听所有元素 是一个数组
callback(entries[0].contentRect) // 元素变化后的宽高都传递给这个函数
})
resize.observe (el) // 监听的元素
}
、、 创建自定义指令
import type {App} from 'vue'
const install = (app:App)=>{
app.directive('resize',{
mounted(el,binding){
useResize(el,binding.value)
}
})
}
useResize.install = install
03 定义全局的变量或者函数并使用
定义全局的变量或者函数在main.ts文件中
const app = createApp(app)
app.config.globalProperties.$env = 'dev'
使用的方法:
在组件中直接使用就可以
模板中直接使用 <div>{{$env}}</div>
script中使用:
const app = getCurrentInstance()
console.log(app.proxy.$env)
04 css完整的特性:
01 插槽选择器:
插槽组件:
<template>
<div>我是插槽组件</div>
<div> <slot></slot> </div>
</template>
父组件:
<template>
<son>
<div class="a">传递给插槽的数据</div>
</son>
</template>
出现的问题 : 在父组件定义插槽的内容 div类名为a的标签 如果想在插槽组件修改样式我无法修改的
解决的办法 : 在插槽组件中使用插槽选择器 :slotted(.a){color:'red'} 就可以修改样式了
02 全局选择器:
如果在一个组件内想要给所有的div属性都绑定一个样式的话可以使用全局选择器
<style scoped>
:global(div){
color:'red'
}
</style>
03 动态的css
<template>
<div class="div">动态css</div>
</template>
<script>
const style = ref('pink')
</script>
<style>
.div{
color:v-bind(style)
}
</style>
04 模块块化的css
<div :class=[$style.div,$style.border]></div>
<style module>
.div {color:'red'}
.border{border:1px soild #ccc}
</style>
05 tailwind/css的使用:
第一步 :初始化一个vue的项目:
npm init vue@latest
第二步 :安装vscode插件
tailwind css intelliSense 安装并启动
第三步 安装相关依赖:
npm install -D tailwindcss@latest postcss@latest autoprefixer@latest
第四步 生成配置文件
npm tailwindcss init -p
第五步 修改配置文件 tailwind.config,js
2.6版本:
module.exports ={
purge:['./index.html','./src/**/*.{vue,js,ts,jsx,tsx}'],
theme:{
extend:{},
},
plugins: [],
}
3.0版本
module.exports={
content:./index.html',"./src/**/*.{vue,js,ts,jsx,tsx}'],
theme:{
extend:{}
},
plugins:[],
}
第六步 创建一个index.css
@tailwindbase;
@tailwindcomponents;
@tailwindutilities;
第七步 在main.ts文件中引入上面的index.css
第八步 组件内部的标签就可以直接使用了
<div class="w-screen h-screen
bg-red-600 flex justify-center items-center text-8xl
text-slate-200"></div>
05 关于nextTick
vue更新数据是同步的,但是vue更新DOM是异步:
案例: 添加内容,屏幕出现滚动条,让每次添加的内容屏幕滚动都在最下面。
const send = async ()=>{
messageList.push('xiaoman') // 追加内容
box.value.scrollTop = 99999999 // 卷去头部让其滚动到最下面问题:无法实现因为是异步的操作
// 第一种解决办法
nextTick(()=>{box.value.scrollTop = 99999999 })
// 第二种办法
await nextTick()
box.value.scrollTop = 99999999
}
原理 把我们的代码放到一个promise里面去执行, 执行的是then方法 走的是一个微任务