看文档是解决问题最快的方式
先看之前大屏端的监控部分全屏代码





整块全屏代码
常规流是下面这种
//进入全屏
function full(ele) {
//if (ele.requestFullscreen) {
// ele.requestFullscreen();
//} else if (ele.mozRequestFullScreen) {
// ele.mozRequestFullScreen();
//} else if (ele.webkitRequestFullscreen) {
// ele.webkitRequestFullscreen();
//} else if (ele.msRequestFullscreen) {
// ele.msRequestFullscreen();
//}
const funcNames=[
'requestFullscreen',
'mozRequestFullScreen',
'webkitRequestFullscreen',
'msRequestFullscreen',
]
const name=funcNames.find(funcName=>funcName in ele)
name&&ele[name]()
}
//退出全屏
function exitFullscreen() {
if(document.exitFullScreen) {
document.exitFullScreen();
} else if(document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if(document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if(document.msExitFullscreen) {
document.msExitFullscreen();
}
}
//监控全屏
window.onresize = () => {
// 全屏下监控是否按键了ESC
//that.isFull = this.isFullScreenFunc()
}
//判断全屏
isFullScreenFunc() {
return !!(
document.fullscreen ||
document.mozFullScreen ||
document.webkitIsFullScreen ||
document.webkitFullScreen ||
document.msFullScreen
)
},
//获取全屏节点
function getFullscreenElement() {
return (
document.fullscreenElement ||
document.mozFullScreenElement ||
document.msFullScreenElement ||
document.webkitFullscreenElement||null
);
}
提高
function getPropertyName(names,target){
return names.find(name=>name in target)
}
const enterFullScreen=getPropertyName([
'requestFullscreen',
'mozRequestFullScreen',
'webkitRequestFullscreen',
'msRequestFullscreen',
],document.documentElement)
export function enter(ele){
enterFullScreen&&ele[enterFullScreen]()
}
//获取全屏节点
const fullEleName=getPropertyName([
'fullscreenElement',
'mozFullScreenElement',
'msFullScreenElement',
'webkitFullscreenElement',
],document.documentElement)
export function getElement(){
return document[fullEleName]||null
}



KOA洋葱模型
状态库vuex和pinia,存储在内存中,一旦刷新数据没了,在和同事探讨时,发现数据是存储在session和local里,再取出来
1、vuex
2、pinia

一张小图一张大于4M大图,
开发环境里打印的是正常绝对路径,
生产环境大于4M图自动变成base64

第一种方法是动生产环境,修改配置,小于4096就自动转换,改成0

第二种方法是动开发环境,自己写vite插件,

写个插件小于4096在开发环境转成base64,
【题外:code ai代码补全】

打印的id是文件的绝对路径

导入fs模块
import fs from ‘node:fs’
await fs.promise.stat(id)//stat文件状态,是异步的
下面是上面await的打印对象


如果大于4096才需要转换,
读取文件,是buffer对象,转base64

vite是由esbuild和rollup组成,
transform是rollup的钩子函数,做代码转换用的

需求是:把写死的base64放在图片img标签src下
但是这样写不太优雅
提取出去,比方说放在同级的img.dataUrl文件下,随便取的
1、vue-cli
import dataUrl from ‘./img.dataUrl’

直接导入会报错,没有loader来处理的错误

整个vue是用webpack搭建的,默认可以处理*.js文件,于是其他文件需要loader来处理
.css css-loader
img file
但是.dataUrl没有loader来处理
所以需要配置loader,我们是希望获得文件内容,所以需要用到raw-loader
如何在vue-cli里面配置webpack

2、vite
直接加?raw

只有 NODE_ENV,BASE_URL 和以 VUE_APP_ 开头的变量

lodash


最强大的就是函数形式
// 格式化时间函数,参数归一化 该函数主要用来处理不用的 参数类型 例如 'date' 'datetime' 'yyyy-MM-dd HH:mm:ss' 等等
function _formatNormalize(formatter) {
if (typeof formatter === 'function') {
return formatter;
}
if (typeof formatter !== 'string') {
throw new TypeError('formatter must be a string');
}
if (formatter === 'date') {
formatter = 'yyyy-MM-dd';
} else if (formatter === 'datetime') {
formatter = 'yyyy-MM-dd HH:mm:ss';
} else if (formatter === 'date') {
formatter = 'yyyy-MM-dd';
}
//将格式化好的formatter里面的占位符替换成真实数据
const formatterFunc = (dateInfo) => {
return formatter.replace(/yyyy|MM|dd|HH|mm|ss|SSS/g, (matched) => {
return dateInfo[matched];
});
//replace用法
};
return formatterFunc;
}
上方代码是下面代码的优化

// 格式化时间函数
function formatDate(date, formatter, isPad = true) {
formatter = _formatNormalize(formatter);
const dateInfo = {
year: date.getFullYear(),
month: date.getMonth() + 1,
date: date.getDate(),
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
miniSecond: date.getMilliseconds()
};
//再写一份用来匹配规则
const dateFeildArr = ['yyyy', 'MM', 'dd', 'HH', 'mm', 'ss', 'SSS'];
const dateInfoKeys = Object.keys(dateInfo);
dateFeildArr.forEach((feild, index) => {
dateInfo[feild] = dateInfo[dateInfoKeys[index]].toString();
});
function _pad(prop, len = 1) {
dateInfo[prop] = dateInfo[prop].padStart(len, '0');
}
if (isPad) {
dateFeildArr.forEach((feild) => {
const len = feild.length;
_pad(feild, len);
});
}
return formatter(dateInfo);
}
padStart() 方法有两个参数:

禁止props里的值直接修改,因为要保护单项数据流
父传子,子组件直接修改的话,会导致数据脱钩,
比方说,下图的子组件修改了变成3,父组件没修改,还是8,导致显示异常

只有数据的拥有者有资格修改数据

用$emit(或其他)抛出事件给父组件,然后props单向
index.js
// 三个参数
// directory {String} -读取文件的路径
// useSubdirectories {Boolean} -是否遍历文件的子目录
// regExp {RegExp} -匹配文件的正则
// require.context(‘./test’, false, /.test.js$/);
// 上面的代码遍历当前目录下的test文件夹的所有.test.js结尾的文件,不遍历子目录
const contexts = require.context('./', false, /\.vue$/)
const components = []
let removeList = [] //要排除某个文件
contexts.keys().forEach(key => {//遍历子目录
const name = key.replace(/(\.\/|\.vue)/g, '')
removeList.includes(name) ? '' : components[name] = resolve => require([`${key}`], resolve)
})
//由export default改为 export
export {
components
}

父组件给子组件通常通过props传值,如果需要做一些强校验则可以使用validator
如父组件传入一个propType参数,规定只能传入’text’, 'number’或者’letter’其中一种就可以这么写:
props: {
propType: {
type: String,
default: 'text',
validator() {
return ['text', 'number','letter'].indexOf(propType) > -1
}
}
}
又或者你想传入一个参数,但是想限制它的长度,那你也可以使用validator进行强校验
props: {
lintLength: {
type: Array,
default: () => [],
validator() {
return lintLength.length < 6
}
}
}
深受启发
https://blog.csdn.net/weixin_66375317/article/details/124673576

v-slot: 可以简化成#


默认插槽 =》1. 子组件标签下不使用template写html结构 2. 子组件通过
具名插槽 => 1. 子组件标签下使用template =》包裹传递html结构 =》template上提供名字#插槽名 2. 子组件通过传递数据=》子传父
作用域插槽=> 1. 子组件
Scoped slot 比较有趣,但为了使用它们,你也必须使用很多template标签。
然而有一个速记可以让我们摆脱它,但前提是我们使用单个作用域slot。
可以不用这样写:
<DataTable>
<template #header="tableAttributes">
<TableHeader v-bind="tableAttributes" />
</template>
</DataTable>
可以这么写:
<DataTable #header="tableAttributes">
<TableHeader v-bind="tableAttributes" />
</DataTable>
1、原理
布局方式
先flex横轴、纵轴居中,
然后margin-left:auto,元素会跑最右边,左外边距会吃掉剩余空间,
其他同理
2、例子
单独设置

第三个元素margin-left:auto

第三个元素margin:0 auto

等分布局,进行计算


可以去掉所有标签
function removeTag(fragment) {
return (
new DOMParser()
.parseFromString(fragment, 'text/html')
.body
.textContent || ''
//new DOMParser()
)
}
var fragment = `
手动解析DOM
DOMParser 可以将存储在字符串中的 XML 或 HTML 源代码解析为一个 DOM Document。
相反,你可以使用XMLSerializer 接口执行相反的操作 - 将 DOM 树转换为 XML 或 HTML 源。
对于 HTML 文档,您还可以通过设置 Element.innerHTML 和outerHTML 属性的值,将部分 DOM 替换为从 HTML 构建的新 DOM
树。还可以读取这些属性以获取对应于相应 DOM 子树的 HTML 片段。
`
console.log(removeTag(fragment))

IE6IE8不兼容
在我们写前端时,可能需要去获取DOM文档里面的纯文本。这里给大家介绍一个浏览器API,我们都知道浏览器在渲染时,DOM文档会被解析生成DOM树,而此过程它就需要靠DOMParse这个API来完成。
DOMParse的作用,官方文档是这样定义的,DOMParser 可以将存储在字符串中的 XML 或 HTML 源代码解析为一个 DOM Document。
第二部分是运用DOMParse解析DOM文档的具体实践过程。
1、在哪命名
第一种
components:{}

abc是组件的名字
第二种
全局组件

Vue.component('组件名',导入的组件);
2、怎么命名、怎么用


最好使用大驼峰,可以用ES6简写,短横线不能简写
第四点是直接引用vue的cdn意思,命名可以大驼峰,使用只能用短横线,因为在这种开发模式下,是写在页面层面的,交给浏览器先来读取,浏览器看到大驼峰会以为你写错了,就会出现纠错机制,然后改成小写,然后读到vue.js后,一看模板里的标签全是小写,就跟组件对应不上了
工程化是给构建工具看的

name属性跟组件命名无关
1)图片是宽高固定的情况下
页面上有个图片标签,img设置了固定宽高
假如有一张特别模糊的图片,在浏览器和电脑层面进行缩放,会导致图片特别模糊
最终会有一个最终的缩放倍率
可以用window.devicePixelRatio进行查看

关系到图片特别模糊的原因一个是设备像素,一个是css像素
6表示的是DPR,css像素在横向和纵向上将占用6个设备像素,因此变模糊了
为了清晰,图像的尺寸=DPR*CSS尺寸
就是说img{150px}图片是300像素,dpr是2,就是清晰的

srcset设置的时候src属性可以不写,DPR如果是3倍,那么就是往上取4x那张图,不然就会去取最近的那一项,1x是默认值可以不写
2)图片是宽高不固定的情况下
图像的尺寸=DPR*CSS尺寸,是CSS尺寸在变

w是物理像素,sizes里面写的是媒介查询

屏幕宽度为300px以下的时候,按照150px像素来算

在不同情况下确定css尺寸,浏览器会基于这个尺寸来乘DPR,然后得到图像尺寸
假如屏幕尺寸是800px,被第三条匹配上了,图片宽度看做50vw,800和50一结合就是400px的css尺寸,DPR假设为2,那么就是800px的图像尺寸,去上面找就是上面第四条

前面带0尝试转换成8进制,转换不成功就转10进制
所以正经写八进制就是0o10(16进制0x,2进制0b)
输出8

1e10,10次方
11.toString()会报错,需要11…toString(),第一个表示小数点,第二个表示方法
https://www.douyin.com/user/MS4wLjABAAAAeIIkCgELXG6XdUxuE9nQ6W4AfS-aoPFbtmnBL8ytcYtBSyurgePBYZXJpB0LJBCT?is_search=0&list_name=follow&modal_id=7254919523126512935&nt=3
https://www.douyin.com/user/MS4wLjABAAAAi2oukRVcHpgD-HbVdzsxE7tYykr91YuIKukR_X_Yy08EFWRQhRrECDF6FvbvT8Xa?is_search=0&list_name=follow&modal_id=7296071965088009526&nt=0

属性描述符:它表达了一个属性的相关信息(元数据)它本质上是一 个对象。
1、数据属性(常规的)
2、存储器属性
- 当给它赋值,会自动运行一个函数
- 当获取它的值,会自动运行一个函数
const object1 = {};
Object.defineProperty(object1, 'property1', {
//value: 42,
//writable: false,
get:()=>{
console.log('读取属性x')
return 2
},//当读取property1属性时,运行的函数,并且将该函数的返回值作为属性的值
set:(val)=>{console.log('给属性赋值为'+val)},//当给property1属性赋值时,运行的函数,并且将该函数的返回值作为属性的值
});//object1.property1=42
object1.property1 = 77;//相当于运行了set(77)
console.log(object1.property1)//面试题:会输出什么?
//赋值操作,给属性赋值为77
//console读取,读取属性x
//2

no表示无效




第一个例子

控制台打印如下,
调用getter属性

点省略号

第二个例子


第三个例子

//运行了set-1
//运行了get
//运行了set10000(-1保存进去为0,0+10000)
//运行了get
//100
反弹小球

<Style>
#box {
position: fixed;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: red;
left: 0;
top: 0;
}
</Style>
<body>
<div id="box"></div>
</body>
<script>
var div = document.getElementById("box");
var X = 0, //初始坐标X
Y = 0, //初始坐标Y
disX = 3, //每次移动x的距离
disY = 3, //每次移动y的距离
height = 100,
width = 100,
frequency = 14;
setInterval(function () {
X += disX;
Y += disY;
//边界判定
if (Y >= document.documentElement.clientHeight - height) {
Y = document.documentElement.clientHeight - height;
disY *= -1;
}
if (Y <= 0) {
Y = 0;
disY *= -1;
}
if (X >= document.documentElement.clientWidth - width) {
X = document.documentElement.clientWidth - width;
disX *= -1;
}
if (X < 0) {
X = 0;
disX *= -1;
}
div.style.left = X + "px";
div.style.top = Y + "px";
}, frequency);
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<Style>
#box {
position: fixed;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: red;
left: 0;
top: 0;
}
</Style>
</head>
<body>
<div id="box"></div>
</body>
<script>
var div = document.getElementById("box");
let config={
_x:0,
_y:0,
X:0,
Y:0,
disX : 3, //每次移动x的距离
disY : 3, //每次移动y的距离
duration:16,//移动的间隔时间
height : 100,
width : 100,
}
Object.defineProperty(config,"x",{
get(){
return this._x
},
set(val){
if(val<0){
val=0
}else if(val> document.documentElement.clientWidth - width){
val=document.documentElement.clientWidth - width
}
// this.x=val//这样赋值又会运行set,无限递归下去
this._x=val
div.style.left=val+'px'
}
})
Object.defineProperty(config,"y",{
get(){
return this._y
},
set(val){
if(val<0){
val=0
}else if(val> document.documentElement.clientWidth - width){
val=document.documentElement.clientWidth - width
}
// this.x=val//这样赋值又会运行set,无限递归下去
this._y=val
div.style.top=val+'px'
}
})
setInterval(function () {
config.X += config.disX;
config.Y += config.disY;
//边界判定
if (config.Y >= document.documentElement.clientHeight - config.height) {
config.Y = document.documentElement.clientHeight - config.height;
config.disY *= -1;
}
if (config.Y <= 0) {
config.Y = 0;
config.disY *= -1;
}
if (config.X >= document.documentElement.clientWidth - config.width) {
config.X = document.documentElement.clientWidth - config.width;
config.disX *= -1;
}
if (config.X < 0) {
config.X = 0;
config.disX *= -1;
}
div.style.left = config.X + "px";
div.style.top = config.Y + "px";
}, config.duration);
</script>
</html>


Object.defineProperty(config,"y",{
configurable:true,
get:function(){
return this._y
},
...

var obj={}
//obj的name属性值固定为abc,且不能被重新赋值
//1、存取器方式
Object.defineProperty(obj,"name",{
get:function(){
return "abc"
},
})
//2、
Object.defineProperty(obj,"name",{
value:'abc',
writable:false,//可以不设置默认false
})
var obj={
x:1,y:2
}
Object.defineProperty(obj,"name",{
value:'abc',
writable:false,//可以不设置默认false
enumerable:false
})
遍历没有name属性

Object.getOwnPropertyDescriptor(obj,'name')

Object.getOwnPropertyDescriptor(document.body.__proto__.__proto__,'innerText')





朋友项目的




在项目上应用了一下

<div class="more" @click="show.bottom=true" :style="{bottom:bottom+'px'}"
@touchmove.prevent="position">
<img src="@/assets/imgs/more.png" alt="">
<div>更多</div>
</div>
position(e) {
console.log(e.touches[0].clientY)
//bottom要大于96不触底,且不超出最上方导致更多消失
if (document.documentElement.clientHeight - e.touches[0].clientY < 96) {
this.bottom = 96
} else if (e.touches[0].clientY > 85) {
this.bottom = document.documentElement.clientHeight - e.touches[0].clientY
}
},