2.3 css开发技巧
2.3.1 巧妙使用伪类生成表单必填标识
::befor { content: "*"; color: red; margin-right: 4px; }
示例:(element ui里面的表单项必填标识)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dGYZMG1q-1682384948779)(前端代码整洁与开发技巧.assets/1673255318557.png)]
2.3.2 增强用户体验,使用伪元素实现增大点击热区
在移动端,按钮通常都很小,但是有时由于设计稿限制,我们不能直接去改变按钮元素的高宽。那么这个时候有什么办法在不改变按钮原本大小的情况下去增加他的点击热区呢?
这里,伪元素也是可以代表其宿主元素来响应的鼠标交互事件的。借助伪元素可以轻松帮我们实现,如:
.btn::befoer{ content: ""; position: absolute; top: -10px; right: -10px; bottom: -10px; left: -10px; }
2.3.3 利用伪类实现鼠标移入时下划线向两边展开的效果
<html lang="en"> <head> <meta charset="UTF-8"> <title>鼠标移入下划线展开</title> <style type="text/css"> #underline{ width: 200px; height: 50px; background: #ddd; margin: 20px; position: relative; } #underline:after{ content: ""; width: 0; height: 5px; background: blue; position: absolute; top: 100%; left: 50%; transition: all .8s; } #underline:hover:after{ left: 0%; width: 100%; } </style> </head> <body> <div id="underline"></div> </body> </html>
效果展示:
1、在浏览器上随便找个网页打开f12;
2、点击元素栏选中html跟标签右键以html格式修改;
3、复制上述代码覆盖掉网页上的html代码完成修改;
4、鼠标移入显示元素即可看到效果。
三、其它技巧
3.1.1 适时使用provide和inject
provide 和 inject 主要为高阶插件/组件库提供用例,并不推荐直接用于应用程序代码中;并且这对选项需要一起使用以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,在上下游关系成立的时间里始终生效。
- provide:Object | () => Object
- inject:Array | { [key: string]: string | Symbol | Object }
//父组件: provide: { // provide 提供一个属性和方法 foo: '这是 foo', fooMethod: () => { console.log('父组件 fooMethod 被调用') } }, // 子或者孙子组件 inject: ['foo', 'fooMethod'], //数组或者对象,注入到子组件 mounted() { this.fooMethod() console.log(this.foo) } //在父组件下面所有的子组件都可以利用inject
provide 和 inject 绑定并不是可响应的。这是官方刻意为之的。
然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的,因为对象是引用类型
//父组件: provide: { foo: '这是 foo' }, mounted(){ this.foo = '这是新的 foo' } // 子或者孙子组件 inject: ['foo'], mounted() { console.log(this.foo) //子组件打印的还是'这是 foo' } //父组件: provide() { return { foo: this.foo, nameList: this.nameList, personalInfo: this.personalInfo } }, data() { return { foo: '这是foo', nameList: ['张三', '李四'], personalInfo: { age: 18 } } }, mounted(){ this.foo = '这是新的 foo' this.nameList.push('王五') // 改变堆内存中的值 // this.nameList = ['王五', '赵六'] // 放开后子组件仍打印 ['张三', '李四', '王五'], this.personalInfo.age = 16 // 改变堆内存中的值 this.personalInfo = {age: 12} // 将当前对象的指针指向新的堆内存地址 } // 子或者孙子组件 <template> <div>{{foo}}</div> <div>{{nameList}}</div> <div>{{personalInfo && personalInfo.age}}</div> </template> <script> export default{ inject: ['foo', 'nameList', 'personalInfo'], mounted() { setTimeout(() => { console.log(this.foo) // 这是foo -视图不会更新 console.log(this.nameList) // ['张三', '李四', '王五'] -视图会更新 console.log(this.personalInfo.age) // 16 foo -视图会更新 }, 1000) } } </script>
3.1.2 利用key值解决vue就地复用策略的问题
已知:throttle是封装过的节流指令,在规定时间仅第一次执行,后续点击不再执行,目前设置的时间是2秒,即每2秒内的重复点击只执行第一次。
// 节流指令 Vue.directive('throttle', { inserted: (el, binding) => { const throttleTime = binding.value || 2000 // 节流时间 el.addEventListener('click', event => { if (el.nodeName === 'BUTTON' || el.type === 'button') { if (!el.disabled) { el.disabled = true setTimeout(() => { el.disabled = false }, throttleTime) } } else { // 合理使用样式穿透使元素本身及其子元素鼠标事件失效 el.style.pointerEvents = 'none' el.style.color = 'red' el.setAttribute('data-flag', '0') // 只是为了打印 setTimeout(() => { if (el && el.style) { el.style.pointerEvents = 'auto' el.style.color = '#000' el.setAttribute('data-flag', '1') // 只是为了打印 } }, throttleTime) } }, false) } })
通过以下代码可以发现点击完接受工作票按钮后不到2秒的时间内由于vue的就地复用策略导致工作许可按钮复用了原来的元素,继承了之前的样式和自定义属性,从而导致工作许可按钮在上述2s内的点击不会生效,且颜色也发生了短暂的改变。(利用项目加浏览器调试来演示说明)
<template> <view> <!-- 待接收 --> <button v-if="stateNo == '10'" class="btn-test" @click="ticketReceive" v-throttle>接收工作票</button> <!-- 待许可 --> <button v-if="stateNo == '12'" class="btn-test" @click="permitTicket" v-throttle>工作许可</button> </view> </template> <script> export default{ data() { return { stateNo: '10' } }, methods: { // 接收工作票 ticketReceive($event) { console.log('$event', $event) this.stateNo = '12' this.$nextTick(() => { console.log('视图已完成更新', '工作许可按钮已显示') setTimeout(() => { let dom = document.querySelector('.btn-test') console.log('data-flag', dom.getAttribute('data-flag')) // 0 }, 1000) setTimeout(() => { let dom = document.querySelector('.btn-test') console.log('data-flag', dom.getAttribute('data-flag')) // 1 }, 2600) }) }, permitTicket() { console.log('点击了工作许可') }, } } </script>
解决办法:给两个使用v-if的标签添加不同的key值,如:
<template> <view> <!-- 待接受 --> <button v-if="stateNo == '10'" class="btn-test" @click="ticketReceive" v-throttle key="1">接受工作票</button> <!-- 待许可 --> <button v-if="stateNo == '12'" class="btn-test" @click="permitTicket" v-throttle key="2">工作许可</button> </view> </template>
‘0’) // 只是为了打印 setTimeout(() => { if (el && el.style) { el.style.pointerEvents = ‘auto’ el.style.color = ‘#000’ el.setAttribute(‘data-flag’, ‘1’) // 只是为了打印 } }, throttleTime) } }, false) } })
通过以下代码可以发现点击完接受工作票按钮后不到2秒的时间内由于vue的就地复用策略导致工作许可按钮复用了原来的元素,继承了之前的样式和自定义属性,从而导致工作许可按钮在上述2s内的点击不会生效,且颜色也发生了短暂的改变。(利用项目加浏览器调试来演示说明)
```jsx <template> <view> <!-- 待接收 --> <button v-if="stateNo == '10'" class="btn-test" @click="ticketReceive" v-throttle>接收工作票</button> <!-- 待许可 --> <button v-if="stateNo == '12'" class="btn-test" @click="permitTicket" v-throttle>工作许可</button> </view> </template> <script> export default{ data() { return { stateNo: '10' } }, methods: { // 接收工作票 ticketReceive($event) { console.log('$event', $event) this.stateNo = '12' this.$nextTick(() => { console.log('视图已完成更新', '工作许可按钮已显示') setTimeout(() => { let dom = document.querySelector('.btn-test') console.log('data-flag', dom.getAttribute('data-flag')) // 0 }, 1000) setTimeout(() => { let dom = document.querySelector('.btn-test') console.log('data-flag', dom.getAttribute('data-flag')) // 1 }, 2600) }) }, permitTicket() { console.log('点击了工作许可') }, } } </script>
解决办法:给两个使用v-if的标签添加不同的key值,如:
<template> <view> <!-- 待接受 --> <button v-if="stateNo == '10'" class="btn-test" @click="ticketReceive" v-throttle key="1">接受工作票</button> <!-- 待许可 --> <button v-if="stateNo == '12'" class="btn-test" @click="permitTicket" v-throttle key="2">工作许可</button> </view> </template>