突破常规的前端技巧与方法(四)

简介: 突破常规的前端技巧与方法(四)

三、其它技巧

3.1.1 适时使用provide和inject

provide 和 inject 主要为高阶插件/组件库提供用例,并不推荐直接用于应用程序代码中;并且这对选项需要一起使用以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,在上下游关系成立的时间里始终生效。

  • provideObject | () => Object
  • injectArray | { [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>


目录
相关文章
|
9天前
|
前端开发 JavaScript
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
本文介绍了JavaScript中this的基本使用、this指向的判断以及改变this指向的方法。
23 1
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
|
9天前
|
前端开发
前端基础(十四)_隐藏元素的方法
本文介绍了几种在前端开发中隐藏元素的方法,包括使用`display:none`、`visibility:hidden`、`opacity:0`等CSS属性,并提供了相应的示例代码。此外,还提到了其他隐藏元素的技巧,如通过设置元素位置、使用`overflow`属性和`filter`属性以及`rgba`颜色值来实现元素的隐藏。
29 1
前端基础(十四)_隐藏元素的方法
|
9天前
|
前端开发
前端基础(十一)_Float浮动、清除浮动的几种方法
本文介绍了浮动的概念、属性、特性以及清除浮动的几种方法,并通过实例演示了如何使用CSS实现元素的浮动和处理浮动带来的问题。
28 3
|
1月前
|
前端开发 JavaScript
前端ES5 | js —添加元素方法
前端ES5 | js —添加元素方法
|
5月前
|
前端开发 JavaScript
前端 js 经典:数组常用方法总结
前端 js 经典:数组常用方法总结
44 0
|
2月前
|
JavaScript 前端开发 开发者
JS 继承之谜:究竟有哪些神秘方法?Web 前端开发者必知的关键技巧待你揭开谜底!
【8月更文挑战第23天】JavaScript (JS) 是 Web 前端开发的关键语言,其中继承是面向对象编程的重要概念。本文探讨了 JS 中几种继承机制:原型链继承、构造函数继承及组合继承。原型链继承利用原型对象实现属性和方法的共享;构造函数继承通过在子类构造器内调用父类构造器实现私有属性的复制;组合继承结合两者优点,既支持属性共享又避免了属性被意外覆盖的风险。理解这些模式有助于开发者更高效地组织代码结构,提升程序质量。
29 1
|
2月前
|
Java 开发者 关系型数据库
JSF与AWS的神秘之旅:如何在云端部署JSF应用,让你的Web应用如虎添翼?
【8月更文挑战第31天】在云计算蓬勃发展的今天,AWS已成为企业级应用的首选平台。本文探讨了在AWS上部署JSF(JavaServer Faces)应用的方法,这是一种广泛使用的Java Web框架。通过了解并利用AWS的基础设施与服务,如EC2、RDS 和 S3,开发者能够高效地部署和管理JSF应用。文章还提供了具体的部署步骤示例,并讨论了使用AWS可能遇到的挑战及应对策略,帮助开发者更好地利用AWS的强大功能,提升Web应用开发效率。
51 0
|
2月前
|
移动开发 前端开发 JavaScript
前端表单验证的完美攻略:HTML5属性与JavaScript方法的无缝对接,让你的Web应用数据输入既安全又优雅
【8月更文挑战第31天】本文介绍前端表单验证的重要性及其实现方法,利用HTML5的内置属性如`required`、`pattern`和`minlength`进行基本验证,并借助JavaScript处理复杂逻辑,如密码确认。通过示例代码详细展示了如何结合两者实现高效且友好的表单验证,同时使用CSS增强用户体验。此方法简化开发流程并提升验证效果。
35 0
|
2月前
|
存储 前端开发 开发者
Web 前端热点来袭!数组去重难题何解?快来探索这些超实用方法,引发开发者共鸣!
【8月更文挑战第23天】在Web前端开发中,去除数组中的重复项是提升数据准确性和效率的关键步骤。本文介绍了四种常用的数组去重方法:一是运用ES6的Set数据结构,通过构造Set对象并转换回数组,快速剔除重复值;二是结合for循环与`indexOf`方法,逐个检查元素是否已存在于新数组中;三是采用`forEach`循环与`includes`方法实现类似功能;四是利用`reduce`方法,以函数式编程方式完成累积检查和去重。这四种方法各有优势,可根据项目需求和环境选择使用。
50 0
|
3月前
|
前端开发 Java 项目管理
List.of 问题之使用List.of方法为什么会引发前端解析失败的问题,如何解决
List.of 问题之使用List.of方法为什么会引发前端解析失败的问题,如何解决
下一篇
无影云桌面