我爱上班
为什么全是字母多行省略不生效 .item { width: 100px; overflow:hidden; text-overflow:ellipsis; display: -webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; } abcdefghijhlmnljjasufoqwhfesadhfjasdflasdjfalsfjla;skdnfvkasldjlsafpwqeuriwehfklsdahvjsahdf "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/5047e0528e38bd4da79de6508feb82c4.png) 文字多行省略生效 .item { width: 100px; overflow:hidden; text-overflow:ellipsis; display: -webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:3; } 哈哈哈哈哈哈哈哈哈哈哈哈哈红红火火恍恍惚惚 "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/8b8229a2e4b65c15c7af24631b677c3c.png)
春暖花又开
想要覆盖antd的默认样式, // AntdCustomStyle/index.module.css :global( .ant-tabs-tab { background-color: red; } ) // AntdCustomStyle/index.tsx import React, { useState } from 'react' import {Tabs} from 'antd' import './index.module.css' const initialItems = [ { label: 'Tab 1', children: 'Content of Tab 1', key: '1' }, { label: 'Tab 2', children: 'Content of Tab 2', key: '2' }, { label: 'Tab 3', children: 'Content of Tab 3', key: '3', closable: false, }, ]; function index() { const [items, setItems] = useState(initialItems); return ( ) } export default index 但是却报错如下: ./pages/components/AntdCustomStyle/index.module.css:3:3 Syntax error: /Users/john/Desktop/Test/js/typescript/ts-test01/my-app/pages/components/AntdCustomStyle/index.module.css Unknown word 1 | 2 | :global( > 3 | .ant-tabs-tab { | ^ 4 | background-color: red; 5 | } "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/983393a4ab9dca85d93fa3bc9f24ad04.png) 请问这是哪里有问题啊,应该就是这样写的? *** 编辑1 感谢:然后去远足的回复。但是我这样做之后还是报错: :global(.ant-tabs-tab ){ background-color: red; } 或者 .myClass { :global(.ant-tabs-tab ){ background-color: red; } } "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250105/7a204d535091b852023a3068a53da58d.png)
codbad
function setAttrsToElement(el: HTMLElement, attr: Record) { for (const key in attr) { el.setAttribute(key, attr[key]) } } 1. 第一个参数是一个element 类型。 2. 第二个参数我想约束为 css 属性。 这个函数接收两个参数,这个函数会遍历第二个参数的 key value 附加给 el 作为属性。 想达到的目的: 在调用这个函数时,代码可以提示自动补全出属性值。 问题补充,在 ts 4.6.4 下 "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241225/c7a9a99cec05db090f7b1a1862613bfc.png)
sssssjkl
unocss 配置 "prefix" 后 className 显得有点长了,我希望只加一个 "data-uno" 来让 unocss 生效,而不是每个 className 都添加前缀。 请问有办法做到这种效果吗? 不生效: 生效:
萌蒙萌
浏览器打印,可以自定义页眉页脚吗? "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241221/760e01ede6e15bfa7865ecc034a0755b.png)
脑洞大咖
我花了几天的时间用vue写了一个五子棋,与机器人对战 但是我感觉里面代码很多重复的部分,想要简化写法,希望大家帮我看看 五子棋 机器人小福正持黑棋与您作战 人机对战 {{ tip }} 重新开始 import { ref } from 'vue' import dialogVue from '../comm/dialog.vue' export default { components: { dialogVue }, setup() { //机器人玩五子棋的思路是 //当用户有三个连在一起时,挡住一边,有四个时,阻挡用户,其他情况机器人自己企图完成五个连线 const isMachine = ref(false)//是否是机器人对战 const score = ref(0) const row = ref(20) const col = ref(20) const visible = ref(false) const tip = ref('') const boxs = ref([[{ place: 0, x: 0, y: 0 }]]) const curUser = ref(1)//只可以是1或者2 1表示白 2表示黑 let airPlace = []//记录机器人下棋子的地方 let previousBox = { place: 0, x: 0, y: 0 } let fourDetial = {}//机器人是否有四个连在一起 function init() { curUser.value = 1 visible.value = false airPlace = [] boxs.value = [] previousBox = { place: 0, x: 0, y: 0 } fourDetial = {} for (let i = 0; i fourDetial.x - fourDetial.times + 1; i--) { if (boxs.value[i][fourDetial.y].place === 0) { boxs.value[i][fourDetial.y].place = 2 fourDetial = determineEquare3(4, 2, { x: i, y: fourDetial.y, place: 2 }) airPlace.push((i) * row.value + fourDetial.y) curUser.value = 1 return } } } else if (boxs.value[fourDetial.x + 1]?.[fourDetial.y]?.place === 0) { boxs.value[fourDetial.x + 1][fourDetial.y].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x + 1, y: fourDetial.y, place: 2 }) airPlace.push((fourDetial.x + 1) * row.value + fourDetial.y) curUser.value = 1 return } else if (boxs.value[fourDetial.x - fourDetial.times]?.[fourDetial.y]?.place === 0) { boxs.value[fourDetial.x - fourDetial.times][fourDetial.y].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x - fourDetial.times, y: fourDetial.y, place: 2 }) airPlace.push((fourDetial.x - fourDetial.times) * row.value + fourDetial.y) curUser.value = 1 return } } else if (fourDetial.type === 2) { if (fourDetial.geyi) { for (let j = fourDetial.y; j > fourDetial.y - fourDetial.times + 1; j--) { if (boxs.value[fourDetial.x][j].place === 0) { boxs.value[fourDetial.x][j].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x, y: j, place: 2 }) airPlace.push((fourDetial.x) * row.value + j) curUser.value = 1 return } } } else if (boxs.value[fourDetial.x]?.[fourDetial.y + 1]?.place === 0) { boxs.value[fourDetial.x][fourDetial.y + 1].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x, y: fourDetial.y + 1, place: 2 }) airPlace.push((fourDetial.x) * row.value + fourDetial.y + 1) curUser.value = 1 return } else if (boxs.value[fourDetial.x]?.[fourDetial.y - fourDetial.times]?.place === 0) { boxs.value[fourDetial.x][fourDetial.y - fourDetial.times].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x, y: fourDetial.y - fourDetial.times, place: 2 }) airPlace.push((fourDetial.x) * row.value + fourDetial.y - fourDetial.times) curUser.value = 1 return } } else if (fourDetial.type === 3) { if (fourDetial.geyi) { let i for (let j = fourDetial.y - 1; j > fourDetial.y - fourDetial.times + 1; j--) { i = fourDetial.x - (fourDetial.y - j) if (boxs.value[i]?.[j]?.place === 0) { boxs.value[i][j].place = 2 fourDetial = determineEquare3(4, 2, { x: i, y: j, place: 2 }) airPlace.push((i) * row.value + j) curUser.value = 1 return } } } else if (boxs.value[fourDetial.x + 1]?.[fourDetial.y + 1]?.place === 0) { boxs.value[fourDetial.x + 1][fourDetial.y + 1].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x + 1, y: fourDetial.y + 1, place: 2 }) airPlace.push((fourDetial.x + 1) * row.value + fourDetial.y + 1) curUser.value = 1 return } else if (boxs.value[fourDetial.x - fourDetial.times]?.[fourDetial.y - fourDetial.times]?.place === 0) { boxs.value[fourDetial.x - fourDetial.times][fourDetial.y - fourDetial.times].place = 2 fourDetial = determineEquare3(4, 2, { x: fourDetial.x - fourDetial.times, y: fourDetial.y - fourDetial.times, place: 2 }) airPlace.push((fourDetial.x - fourDetial.times) * row.value + fourDetial.y - fourDetial.times) curUser.value = 1 return } } else if (fourDetial.type === 4) { if (fourDetial.geyi) { let i for (let j = fourDetial.y; j temp.x - temp.times + 1; i--) { if (boxs.value[i][temp.y].place === 0) { boxs.value[i][temp.y].place = 2 fourDetial = determineEquare3(4, 2, { x: i, y: temp.y, place: 2 }) airPlace.push((i) * row.value + temp.y) } } } else if (boxs.value[temp.x + 1]?.[temp.y]?.place === 0) { boxs.value[temp.x + 1][temp.y].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x + 1, y: temp.y, place: 2 }) airPlace.push((temp.x + 1) * row.value + temp.y) } else if (boxs.value[temp.x - temp.times]?.[temp.y]?.place === 0) { boxs.value[temp.x - temp.times][temp.y].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x - temp.times, y: temp.y, place: 2 }) airPlace.push((temp.x - temp.times) * row.value + temp.y) } } else if (temp.type === 2) { if (temp.geyi) { for (let j = temp.y; j > temp.y - temp.times + 1; j--) { if (boxs.value[temp.x][j].place === 0) { boxs.value[temp.x][j].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x, y: j, place: 2 }) airPlace.push((temp.x) * row.value + j) } } } else if (boxs.value[temp.x]?.[temp.y + 1]?.place === 0) { boxs.value[temp.x][temp.y + 1].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x, y: temp.y + 1, place: 2 }) airPlace.push((temp.x) * row.value + temp.y + 1) } else if (boxs.value[temp.x]?.[temp.y - temp.times]?.place === 0) { boxs.value[temp.x][temp.y - temp.times].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x, y: temp.y - temp.times, place: 2 }) airPlace.push((temp.x) * row.value + temp.y - temp.times) } } else if (temp.type === 3) { if (temp.geyi) { let i for (let j = temp.y - 1; j > temp.y - temp.times + 1; j--) { i = temp.x - (temp.y - j) if (boxs.value[i]?.[j]?.place === 0) { boxs.value[i][j].place = 2 fourDetial = determineEquare3(4, 2, { x: i, y: j, place: 2 }) airPlace.push((i) * row.value + j) } } } else if (boxs.value[temp.x + 1]?.[temp.y + 1]?.place === 0) { boxs.value[temp.x + 1][temp.y + 1].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x + 1, y: temp.y + 1, place: 2 }) airPlace.push((temp.x + 1) * row.value + temp.y + 1) } else if (boxs.value[temp.x - temp.times]?.[temp.y - temp.times]?.place === 0) { boxs.value[temp.x - temp.times][temp.y - temp.times].place = 2 fourDetial = determineEquare3(4, 2, { x: temp.x - temp.times, y: temp.y - temp.times, place: 2 }) airPlace.push((temp.x - temp.times) * row.value + temp.y - temp.times) } } else if (temp.type === 4) { if (temp.geyi) { let i for (let j = temp.y; j 0) { boxs.value[previousBox.x - 1][previousBox.y].place = 2 airPlace.push((previousBox.x - 1) * row.value + previousBox.y) } else { boxs.value[previousBox.x + 1][previousBox.y].place = 2 airPlace.push((previousBox.x + 1) * row.value + previousBox.y) } } else { let time = [{ time: 0, pre: -1, geyi: false }, { time: 0, pre: -1, geyi: false }, { time: 0, pre: -1, geyi: false }, { time: 0, pre: -1, geyi: false }] airPlace.some((item, index, arr) => { let itemi = Math.floor(item / row.value) let itemj = item % row.value if (time[0].time = 4) { if ((boxs.value[itemi][itemj + 1]?.place === 0 && boxs.value[itemi][itemj + 1]) || (boxs.value[itemi][itemj - time[0].times]?.place === 0 && boxs.value[itemi][itemj - time[0].time])) return true else { //虽然有四个横着,但是这四个横着两边都被挡住了,所以重新再来 time[0] = { time: 0, pre: -1, geyi: false } } } } } if (time[1].pre === -1 || arr[time[1].pre] === item - 1 || (arr[time[1].pre] === item - 2 && !time[1].geyi)) { if (arr[time[1].pre] === item - 2) { if (boxs.value[Math.floor((item - 1) / row.value)][(item - 1) % row.value].place === 0) { time[0].geyi = true } else { return false } } if ((arr[time[1].pre] === item - 1 || arr[time[1].pre] === item - 2) && time[1].time === 0) { time[1].time = 0 time[1].geyi = false } else time[1].time++ if (time[1].time > 3) { time[1].time = 0 } time[1].pre = index } if (time[2].pre === -1 || arr[time[2].pre] === item - 1 || (arr[time[2].pre] === item - 2 && !time[2].geyi)) { if (arr[time[2].pre] === item - 2) { if (boxs.value[Math.floor((item - 1) / row.value)][(item - 1) % row.value].place === 0) { time[0].geyi = true } else { return false } } if ((arr[time[2].pre] === item - 1 || arr[time[2].pre] === item - 1) && time[2].time === 0) { time[2].time = 0 time[2].geyi = false } else time[2].time++ if (time[2].time > 2) { time[2].time = 0 } time[2].pre = index } if (time[3].pre === -1 || arr[time[3].pre] === item - 1 || (arr[time[3].pre] === item - 2 && !time[3].geyi)) { if (arr[time[3].pre] === item - 2) { if (boxs.value[Math.floor((item - 1) / row.value)][(item - 1) % row.value].place === 0) { time[0].geyi = true } else { return false } } if ((arr[time[3].pre] === item - 1 || arr[time[3].pre] === item - 1) && time[3].time === 0) { time[3].time = 0 time[3].geyi = false } else time[3].time++ if (time[3].time > 1) { time[3].time = 0 } time[3].pre = index } }) time = time.sort((a, b) => b.time - a.time) let placeHas = time.some(item => { if (item.time > 0 && item.pre > -1) { const i = Math.floor(airPlace[item.pre] / row.value) const j = Math.floor(airPlace[item.pre] % row.value) if (boxs.value[i][j + 1]?.place === 0) { boxs.value[i][j + 1].place = 2 airPlace.push(i * row.value + j + 1) fourDetial = determineEquare3(4, 2, { x: i, y: j + 1, place: 2 }) return true } if (boxs.value[i][j - item.time]?.place === 0) { boxs.value[i][j - item.time].place = 2 airPlace.push(i * row.value + j - item.time) fourDetial = determineEquare3(4, 2, { x: i, y: j - item.time, place: 2 }) return true } } }) if (placeHas) { airPlace = airPlace.sort((a, b) => a - b) return } time = [{ time: 0, pre: -1, index: -1 }, { time: 0, pre: -1, index: -1 }, { time: 0, pre: -1, index: -1 }, { time: 0, pre: -1, index: -1 }] airPlace.some((item, index) => { let itemi = Math.floor(item / row.value) let itemj = item % row.value if (time[0].time = 4) { if ((boxs.value[itemi + 1][itemj]?.place === 0 && boxs.value[itemi + 1][itemj]) || (boxs.value[itemi - time[0].time][itemj]?.place === 0 && boxs.value[itemi - time[0].time][itemj])) return true else { //虽然有四个竖着,但是这四个竖着两边都被挡住了,所以重新再来 time[0] = { time: 0, pre: -1 } } } } } if (time[1].pre === -1 || time[1].pre === item - row.value) { if (time[1].pre === item - row.value && time[1].time === 0) { time[1].time = 0 } else time[1].time++ if (time[1].time > 3) { time[1].time = 0 } time[1].pre = item time[1].index = index } if (time[2].pre === -1 || time[2].pre === item - row.value) { if (time[2].pre === item - row.value && time[2].time === 0) { time[2].time = 0 } else time[2].time++ if (time[2].time > 2) { time[2].time = 0 } time[2].pre = item time[2].index = index } if (time[3].pre === -1 || time[3].pre === item - row.value) { if (time[3].pre === item - row.value && time[3].time === 0) { time[3].time = 0 } else time[3].time++ if (time[3].time > 1) { time[3].time = 0 } time[3].pre = item time[3].index = index } }) time = time.sort((a, b) => b.time - a.time) placeHas = time.some(item => { if (item.time > 0 && item.pre > -1) { const i = Math.floor(item.pre / row.value) const j = Math.floor(item.pre % row.value) if (boxs.value[i + 1]?.[j]?.place === 0) { boxs.value[i + 1][j].place = 2 airPlace.push((i + 1) * row.value + j) fourDetial = determineEquare3(4, 2, { x: i + 1, y: j, place: 2 }) return true } if (boxs.value[i - item.time]?.[j]?.place === 0) { boxs.value[i - item.time][j].place = 2 airPlace.push((i - item.time) * row.value + j) fourDetial = determineEquare3(4, 2, { x: i - item.time, y: j, place: 2 }) return true } } }) if (placeHas) { airPlace = airPlace.sort((a, b) => a - b) return } } } //判断用户是否有横竖斜大于等于3个棋子的情况,只需要查看用户上一个棋子落下后是否造成这样的情况就行 function determineEquare3(maxTime = 3, userPlace = 1, box = previousBox) { let times = 0 let preP = -1 let geyi = false let tempArr = [] //竖 for (let i = (box.x - 5 >= 0 ? box.x - 5 : 0); i = maxTime) { if (times === 3 && geyi) { continue } if (boxs.value[i + 1]?.[box.y].place !== 0 && boxs.value[i + 1]?.[box.y].place !== userPlace && boxs.value[i - times]?.[box.y].place !== 0) { break } else { tempArr[0] = tempArr[0]?.times > times ? tempArr[0] : { x: i, y: box.y, type: 1, times, geyi } if (boxs.value[i + 1]?.[box.y].place !== 0 || boxs.value[i - times]?.[box.y].place !== 0) { tempArr[0].priority = 2 } else { tempArr[0].priority = 1 } } } } } times = 0 preP = -1 geyi = false //横 for (let j = (box.y - 5 >= 0 ? box.y - 5 : 0); j = maxTime) { if (times === 3 && geyi) { continue } if (boxs.value[box.x]?.[j + 1]?.place !== 0 && boxs.value[box.x]?.[j + 1].place !== userPlace && boxs.value[box.x]?.[j - times]?.place !== 0) { break } else { tempArr[1] = tempArr[1]?.times > times ? tempArr[1] : { x: box.x, y: j, type: 2, times, geyi } if (boxs.value[box.x]?.[j + 1]?.place !== 0 || boxs.value[box.x]?.[j - times]?.place !== 0) { tempArr[1].priority = 2 } else { tempArr[1].priority = 1 } } } } } times = 0 preP = -1 geyi = false //左斜 let i let j if (box.x - 5 >= 0 && box.y - 5 >= 0) { i = box.x - 5 j = box.y - 5 } else if (box.x - 5 >= 0 && box.y - 5 = 0) { i = 0 j = box.y - (box.x - i) } else { if (box.x > box.y) { j = 0 i = box.x - (box.y - j) } else { i = 0 j = box.y - (box.x - i) } } for (j; j = maxTime) { if (times === 3 && geyi) { i++ continue } if (boxs.value[i + 1]?.[j + 1]?.place !== 0 && boxs.value[i + 1]?.[j + 1].place !== userPlace && boxs.value[i - times]?.[j - times]?.place !== 0) { break } else { tempArr[2] = tempArr[2]?.times > times ? tempArr[2] : { x: i, y: j, type: 3, times, geyi } if (boxs.value[i + 1]?.[j + 1]?.place !== 0 || boxs.value[i - times]?.[j - times]?.place !== 0) { tempArr[2].priority = 2 } else { tempArr[2].priority = 1 } } } } i++ } //右斜 if (box.x - 5 >= 0 && box.y + 5 = 0 && box.y + 5 >= row.value) { j = row.value - 1 i = box.x - (row.value - 1 - box.y) } else if (box.x - 5 row.value - 1 - box.y) { j = row.value - 1 i = box.x - (row.value - 1 - box.y) } else { i = 0 j = box.y + (box.x - i) } } preP = -1 times = 0 geyi = false for (j; j > (box.y - 5 >= 0 ? box.y - 5 : 0); j--) { console.log(times, preP, geyi, tempArr[0], i, j, box, 'times,preP,geyi,tempArr[0],i,j,box,右斜') if (boxs.value[i]?.[j]?.place === userPlace) { if (preP === -1 || preP === j + 1 || (preP === j + 2 && !geyi)) { if (preP === j + 2) { if (boxs.value[i - 1][j + 1]?.place === 0) { geyi = true times++ } else { continue } } times++ } else { times = 1 geyi = false } preP = j if (times >= maxTime) { if (times === 3 && geyi) { i++ continue } if (boxs.value[i + 1]?.[j - 1]?.place !== 0 && boxs.value[box.x]?.[j - 1].place !== userPlace && boxs.value[i - times]?.[j + times]?.place !== 0) { break } else { tempArr[3] = tempArr[3]?.times > times ? tempArr[3] : { x: i, y: j, type: 4, times, geyi } if (boxs.value[i + 1]?.[j - 1]?.place !== 0 || boxs.value[i - times]?.[j + times]?.place !== 0) { tempArr[3].priority = 2 } else { tempArr[3].priority = 1 } } } } i++ } console.log(tempArr, 'temp') tempArr = tempArr.sort((a, b) => b.times - a.times) if (tempArr[0]?.times >= 3) { if (tempArr[0].priority === 2) { let temp = null tempArr.map((item, index, arr) => { if (item?.times >= arr[0].times) { if (item.priority === 1) { temp = item } } }) if (temp) { return temp } //挡住一边的三个没有必要去阻挡 if (tempArr[0]?.times === 3) { return false } } return tempArr[0] } return false } //验证是否赢了 function validateWin() { if(visible.value) return for (let i = 0; i .mineDlearance { display: flex; justify-content: center; width: 100%; height: 100%; // align-items: center; .game { // background: #ccc; padding: 10px; height: 850px; .top { display: flex; justify-content: space-between; } .game-main { margin-top: 10px; .item-one { width: 40px; height: 40px; border: 1px solid #000; box-sizing: border-box; background: goldenrod; cursor: pointer; .circle { width: 100%; height: 100%; border-radius: 100%; } } } } }
CO_co
现在有一个需求,就是对antd的Collapse做一个样式的修改,去掉border-radius: // TestComp/index.tsx import type { CollapseProps } from 'antd'; import { Collapse, Button } from 'antd'; import styles from './index.module.css' const text = ` A dog is a type of domesticated animal. Known for its loyalty and faithfulness, it can be found as a welcome guest in many households across the world. `; const items: CollapseProps['items'] = [ { key: '1', label: This is panel header 1, children: {text}, }, { key: '2', label: 'This is panel header 2', children: {text}, }, { key: '3', label: 'This is panel header 3', children: {text}, }, ]; const TestComp: React.FC = () => { const onChange = (key: string | string[]) => { console.log(key); }; return ; }; export default TestComp; css代码如下: // TestComp/index.module.tsx .myCollapse:global(.ant-collapse) { border-radius: 0px !important; } /* .myCollapse2:global(.ant-collapse-item:last-child) { border-radius: 0px !important; } */ 效果: 我们可以看到顶部左右是已经去除,但是下面的最后一个item没有去除: "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241231/4ccfe00c4fe605291081e895758a9e6c.png) 所以我进一步想要对".ant-collapse-item:last-child" 做修改: // TestComp/index.module.tsx .myCollapse:global(.ant-collapse) { border-radius: 0px !important; } .myCollapse2:global(.ant-collapse-item:last-child) { border-radius: 0px !important; } // tsx ; 但是不生效: "image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20241231/83bc816506f5a01459727be06c4bf7d5.png) === 请问要如何才能对一个antd组件的多个class做样式修改呢? === 编辑-01 代码如下: "https://codesandbox.io/s/ynk3tr" (https://link.segmentfault.com/?enc=9MBtT68dacU8t3KV8CXDYA%3D%3D.3K7pENa0JsmYnVgSfyxDPGH%2BKt79DM36TItlN0SCxWc%3D)
七安前
网页f12调试如何查看鼠标悬浮时才出现的dom元素
饼干爱折腾
"image.png" (https://wmprod.oss-cn-shanghai.aliyuncs.com/images/20250108/67b17e94dbc4844548d6ef884ca2ea67.png) 这是一个水塔的svg,需求: 水面跟随进度上升下降 进度低于20时变红色,其余进度变绿色 整体尺寸不是固定的,跟随父布局大小 思路1:目前我的思路是根据进度,切10张水塔图,根据进度动态显示。但这增加包体积,感觉也有点粗暴。 思路2:用两张图上下放置,上面的水塔用clip-path根据进度切,但好像只能且固定大小,因为svg的path好像是固定的 目前没有更好的解决思路,各位大佬怎么看?
懒人学前端
一、对比 Less、Sass、Stylus、PostCSS?Less、Sass 和 Stylus 是 CSS 预处理器,PostCSS 是转换 CSS 工具的平台Less变量:$标识符变量,使用{}插值嵌套:支持{ }大括号嵌套混入器:支持 选择器 混入 或 使用.selector(@param)创建纯混入器扩展 / 继承 / 运算符 / @import:支持流程:支持if条件判断,支持when递归模拟循环映射:支持@声明和使用 Map特有:提供 Less.js,直接在浏览器使用 LessSaSS变量:支持$标识符变量,使用#{}插值嵌套:SCSS 支持{ }大括号嵌套 SASS 支持缩进嵌套混入器:@mixin创建@include使用扩展 / 继承 / 运算符 / @import:支持流程:支持if else条件判断,支持for while each循环映射:支持$()声明 Map,提供map-get(map, key) map-keys(map) map-values(map)等一系列方法操作 Map,支持遍历 Map特有:支持 compass ,内含 自动私有前缀 等一系列有用SASS模块,支持压缩输出Stylus变量:支持$标识符变量 和 赋值表达式变量,使用{}插值嵌套:支持{ }大括号嵌套 和 缩进嵌套混入器:像函数一样创建和使用扩展 / 继承 / 运算符 / @import:支持流程:支持if else unless三元 条件判断,支持for循环映射:像 JS 一样创建和使用对象特有:支持中间件,自动分配函数变量,提供 JS API。支持压缩输出PostCSS接受 CSS 文件,把 CSS 规则转换为抽象语法树提供 API 供插件调用,对 CSS 处理插件:支持 Autoprefixer 自动添加私有前缀、css-modules CSS 模块 stylelint CSS 语法检查等插件,PostCSSS 是工具的工具二、Webpack 处理 SASS 文件时,sass-loader, css-loader,style作用sass-loader将 SASS / SCSS 文件编译成 CSS调用node-sass,支持options选项向node-sass传参css-loader支持读取 CSS 文件,在 JS 中将 CSS 作为模块导入支持 CSS 模块 @规则@import @import url()style-loader将 CSS 以<style>标签的方式,插入 DOM配置顺序Webpack中 loader 的加载顺序是从后往前在处理 SASS / SCSS 文件时,三者的配置顺序 style-loader css-loader sass-loader可以用插件 ExtractTextWebpackPlugin 替换 style-loader,生成新的 CSS 文件三、如何压缩 CSS 大小,如何去除无用的 CSS?压缩 CSS ,简单可分为 3 步骤:① 去除 CSS 中的换行和空格② 去除 每个选择器,最后一个属性值后的分号;② 去除 注释,正则/*[^*] [^/][^*]**+)*/此外,包括使用 缩写属性,z-index值的重新排序,也可以减少代码量。但通过工具进行时,结果不一定总是安全常用的 CSS 压缩工具有:YUI Compressor基于 Java , 本来是 JS 压缩,也兼容 CSS 压缩,配置较少,但保障压缩安全clean-css基于 NodeJS , 可以根据 浏览器版本、具体的 CSS 标准模块,详细配置兼容性cssnano基于 PostCSS ,是 Webpack5 推荐的 CssMinimizerWebpackPlugin 默认的 CSS 压缩工具如何去除无用的 CSS :Chrome 开发者工具 Lighthouse打开 http / https 网址,勾选 Performance 选项,在性能报告中,会列出 unused CSS,可以人工去除UnCSS通过 jsdom 加载 HTML 并执行 JS通过 PostCSS 解析样式通过document.querySelector查找 HTML 中不存在的 CSS 选择器返回 剩余样式PurgeCSS可以对 HTML JS 和 VUE 等框架中 CSS 使用情况分析,并删除无用 CSS提供 Webpack Gulp Grunt 等工程化工具的插件cssnano提供discardUnused选项,用于删除与当前 CSS 无关的规则不支持内容分析同样支持工程化工具四、什么是 CSS 模块化,有哪几种实现方式?什么是 CSS 模块化?CSS 模块化是将 CSS 规则 拆分成相对独立的模块,便于开发者在项目中更有效率地组织 CSS:管理层叠关系避免命名冲突提高复用度,减少冗余便于维护或扩展CSS 模块化的方式:基于文件拆分不拆分但设置作用域CSS in JS内联样式、Shadow DOM 等无论哪种方式,核心都是通过 保证CSS类命名唯一,或者 避免命名使用内联样式,来模拟出CSS模块作用域的效果基于文件的 CSS 模块的加载<link>将不同模块的 CSS 分文件存放,通过<link>标签按需引入@import@规则,将其它 CSS 嵌入当前 CSS除现代浏览器外,也得到了 CSS 预处理器 Less、Sass 和 Stylus 的支持import在 Webpack 中,将 CSS 作为资源引入,并可以通过 CSS Modules 为 CSS 生成独一无二的类名CSS 模块化的实现方式分层拆分将 CSS规则 分层存放,并约束不同层次间的命名规则SMACSS:按功能分成 Base Layout Module State Theme 五层ITCSS:按从通用到具体分成 Settings Tools Generic Base Objects Components 七层分块拆分将页面中视觉可复用的块独立出来,仅使用类选择器,并确保类名唯一OOCSS将盒模型规则与颜色、背景等主题规则拆分将视觉可复用的块类名与页面结构解耦BEM将页面按 Block Element Modifier 划分类名规则 block-name__element-name--modifier-name原子化拆分每个选择器只包含1个或少量属性,通过组合选择器定义复杂样式ACSS:属性名像函数,属性值像函数参数,像写内联样式一样组合类名Utility-First CSS:提供一套可配置的 CSS 实用类库,使用时按需编译CSS in JSCSS Modules将 CSS 作为资源引入根据内容的哈希字符串,计算出独一无二的类名,CSS 规则 只对该类名下的元素生效styled-components Aphrodite Emotion 等通过 JS 创建包含属性定义的组件生成独一无二的类名Radium 等通过 JS 创建包含属性定义的组件生成内联样式Shadow DOM通过attachShadow给元素的影子DOM,附加<style>标签,其中规则不会影响外部元素。代表的框架有 Ionic 等五、如何自动压缩图片?使用或调用软件使用 PhotoShop 自动批处理功能录制动作:打开文件,调整大小,另存为调整品质,关闭文件文件菜单,自动,批处理,选择 源文件夹,批量执行动作使用 开源图片处理软件 XnViewr,工具,批量转换功能XnConVenter 提供更复杂的图片批量处理功能使用 命令行工具,包括 NConvert ImageMagic 等以及类似 img2webp 的专门格式的转换工具工程化配置图片压缩这里以Webpack为例CSS 内联图片配置url-loader小于指定尺寸图片转 base64,减少请求module: { rules: [{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10, // 小于10KB图片,转base64编码 } }]}图片模块import / require 到 .js 或 .html 以及 require({图片路径}) 的图片这些图片被打包器看作是资源模块引入配置file-loader+image-webpack-loader调节品质rules: [{ test: /\.png$/i, // 以png为例 use: [ 'file-loader', { loader: 'image-webpack-loader', options: { pngquant: { quality: [0.65, 0.90] // 设置png的品质区间 }, } }, ], }]图片目录图片以静态资源附件的形式,放置在同一目录下通过CopyPlugin将图片从源目录(src)复制到发布目录(dist)可以安装imagemin-webpack-plugin,在复制时,批量调整图片尺寸npm i imagemin-webpack-plugin -D plugins: [ new CopyPlugin({ patterns: [{ from: resolve('src-es6/images'), to: resolve('dist/images'), }] }), new ImageminPlugin({ // 在 CopyPlugin 之后。如果是 merge 多配置文件,CopyPlugin 放 common 被合并的配置里 test: /\.(png|jpe?g)$/i, pngquant: { quality: '70-75' // 设置 png 的品质区间 }, plugins: [ // 可以引入其它图片压缩插件 ImageminMozjpeg({ quality: 70, // 设置 jpeg / jpg 的品质 progressive: true // 渐进式:true:由模糊到清晰加载 false:从上到下加载 }) ] }), ]代码中使用的ImageminMozjpeg需要额外安装,您也可以安装其它压缩插件npm i imagemin-mozjpeg -D使用反向代理部分CDN服务商,提供一键 图片瘦身,自动转 webp 等能压缩图片服务您可以自建反向代理节点,将图片缓存在节点上,根据客户端接受的MIME文件类型列表,如支持 image/webp 的客户端,将图片转成 webp 格式。根据用户 UserAgent,调节品质、尺寸后,再返回给客户端需要提醒的是,避免使用 defalte gzip 和 br 等压缩算法,再次压缩图片,这样带来的性能损耗通常高于传输收益六、如何自动添加浏览器私有前缀属性?使用 SASS自定义添加浏览器私有前缀的Mixins,不能适应所有属性@mixin autoPrefix($propertyName, $propertyValue, $prefixs: ()) { @each $prefix in $prefixs { -#{$prefix}-#{$propertyName}: $propertyValue; } #{$propertyName}: $propertyValue; } div { @include autoPrefix(box-shadow, 0 0 1px black, ('webkit', 'moz')) } 转换为 CSS div { -webkit-box-shadow: 0 0 1px black; -moz-box-shadow: 0 0 1px black; box-shadow: 0 0 1px black; }搭配compass或Bourbon@import "compass/css3"; div { @include box-shadow(0 0 1px black); } 使用 Less,搭配 LESS Elements@import "elements.less"; div { .box-shadow(0 0 1px black); }使用 Autoprefixer支持补全属性值,支持按浏览器兼容情况精确补全VsCode安装 Extensions:Autoprefixer进入 Vscode Perferences Settings 搜索 Autoprefixer配置支持的浏览器版本 "autoprefixer.options": { "browsers": [ "ie >= 6", "firefox >= 8", "chrome >= 24", "Opera >= 10" ] }F1 后,Run Autoprefixer,自动补全Webpack安装并添加 postcss-loadermodule.exports = { module: { rules: [ { test: /\.css$/, use: ["css-loader", "postcss-loader"] } ] } }创建 postcss.config.jsmodule.exports = { plugins: [ require('autoprefixer') ] }创建 .browserslistrcie >= 6 firefox >= 8 chrome >= 24 Opera >= 10或在 package.json 添加 browserslist 属性 { "browserslist": [ "ie >= 6", "firefox >= 8", "chrome >= 24", "Opera >= 10" ] }七·、对比媒体查询与按需引入 CSS?媒体查询允许我们通过设备、屏幕、使用场景、用户偏好来解析符合条件的 CSS,忽略不符合条件的 CSS即使通过 Link 标签附加媒体查询条件引入的 CSS,不符合条件时依然会被下载按需引入按需引入,可以避免冗余下载的问题,允许我们按照目标环境引入CSS但条件没有媒体查询丰富,多数时,无法及时对运行环境的变化作出响应IE 浏览器中,可以通过 HTML 注释,附加 if 条件,阻止其中的 HTML 被解析,相应的 CSS 也不会被下载<!--[if lt IE 9]><link rel="stylesheet" href="ielt9.css" /><![endif]-->工程化及ES6等模块化环境中,我们可以通过import或require只引入需要的css,通过PurgeCSS和cssnano去除未被使用的CSS在webpack配置DefinePlugin自定义环境变量,在uni-app中 使用条件注释等利用打包工具提供的 条件编译 功能