钱的千分,方法 new Intl.NumberFormat
const number = 123456.789;
const formatter = new Intl.NumberFormat('en-US');
console.log(formatter.format(number));
JSON存储map数据
content = JSON.stringify(
{ product_marketing: state.product_marketing, is_finished: state.is_finished },
(key: string, value: any) => {
if (value instanceof Map) {
return {
_type: 'Map',
data: Array.from(value)
};
}
return value;
}
);
JSON.parse(content, (key: string, value: any) => {
if (
value &&
typeof value === 'object' &&
value._type === 'Map' &&
Array.isArray(value.data)
) {
const map = new Map(value.data);
return map;
}
return value;
})
文字打印效果,mardown文本格式,富含代码块。
<style lang="scss" scoped>
.cursor {
content: "";
position: absolute;
width: 10px;
height: 16px;
background: #ff0000;
animation: toggle 0.6s infinite;
opacity: 0;
transform: translateY(3px);
left: calc(v-bind("pos.x") * 1px);
top: calc(v-bind("pos.y") * 1px);
}
@keyframes toggle {
30% {
opacity: 1;
}
}
</style>
<template>
<div
v-html="html"
v-highlight
ref="contentRef"
class="chat-content-container"
></div>
<div
v-show="showCursor"
class="cursor"
ref="cursorRef"
></div>
</template>
<script setup>
import { marked } from "marked";
import hljs from "highlight.js";
import "highlight.js/styles/googlecode.css";
import { onMounted, reactive, ref, watch, nextTick } from "vue";
const contentRef = ref(null);
const cursorRef = ref(null);
const html = ref("");
const vHighlight = {
mounted: (el) => {
let blocks = el.querySelectorAll("pre code");
blocks.forEach((block) => {
hljs.highlightElement(block);
});
},
updated: (el) => {
let blocks = el.querySelectorAll("pre code");
blocks.forEach((block) => {
hljs.highlightElement(block);
});
},
};
const props = defineProps({
str: {
type: String,
default: "",
},
});
const showCursor = ref(false);
const pos = reactive({
x: 0,
y: 0,
});
onMounted(() => {
html.value = marked.parse(props.str);
showCursor.value = false;
});
function getLastTextNode(dom) {
const children = dom.childNodes;
for (let i = children.length - 1; i >= 0; i--) {
const node = children[i];
if (node.nodeType == Node.TEXT_NODE && /\S/.test(node.nodeValue)) {
node.nodeValue = node.nodeValue.replace(/\s+$/, "");
return node;
} else if (node.nodeType == Node.ELEMENT_NODE) {
const last = getLastTextNode(node);
if (last) {
return last;
}
}
}
return null;
}
async function updateCursorPosition() {
await nextTick();
const contentDom = contentRef.value;
if (!contentDom) return;
const cursorElement = document.createElement('span');
cursorElement.textContent = '|';
cursorElement.style.position = 'absolute';
cursorElement.style.visibility = 'hidden';
cursorElement.style.whiteSpace = 'pre';
contentDom.appendChild(cursorElement);
const rect = cursorElement.getBoundingClientRect();
const containerRect = contentDom.getBoundingClientRect();
pos.x = rect.left - containerRect.left;
pos.y = rect.top - containerRect.top + contentDom.scrollTop;
contentDom.removeChild(cursorElement);
}
watch(
() => props.str,
(val, oldVal) => {
if (oldVal) {
return;
} else {
markdownToHtmlDom(val);
}
}
);
const markdownToHtmlDom = (markdown) => {
showCursor.value = true;
let index = 0;
const interval = setInterval(async () => {
if (index <= markdown.length) {
html.value = marked.parse(markdown.substring(0, index));
await nextTick();
updateCursorPosition();
}
if (index >= markdown.length) {
showCursor.value = false;
clearInterval(interval);
}
index++;
}, 100);
};
</script>
获取指定坐标最上层的元素
document.elementFromPoint(x,y)
table表格border合并问题,css解决
border-collapse: collapse;
浏览器自带生成唯一UID
crypto.randomUUID()