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

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

三、其它技巧

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>


目录
相关文章
|
25天前
|
存储 前端开发 JavaScript
前端的全栈之路Meteor篇(四):RPC方法注册及调用-更轻量的服务接口提供方式
RPC机制通过前后端的`callAsync`方法实现了高效的数据交互。后端通过`Meteor.methods()`注册方法,支持异步操作;前端使用`callAsync`调用后端方法,代码更简洁、易读。本文详细介绍了Methods注册机制、异步支持及最佳实践。
|
2月前
|
前端开发 JavaScript
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
本文介绍了JavaScript中this的基本使用、this指向的判断以及改变this指向的方法。
44 1
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
|
2月前
|
前端开发
前端基础(十四)_隐藏元素的方法
本文介绍了几种在前端开发中隐藏元素的方法,包括使用`display:none`、`visibility:hidden`、`opacity:0`等CSS属性,并提供了相应的示例代码。此外,还提到了其他隐藏元素的技巧,如通过设置元素位置、使用`overflow`属性和`filter`属性以及`rgba`颜色值来实现元素的隐藏。
66 1
前端基础(十四)_隐藏元素的方法
|
1月前
|
前端开发 JavaScript
掌握微前端架构:构建现代Web应用的新方法
本文介绍了微前端架构的概念及其在现代Web应用开发中的优势与实施方法。微前端架构通过将应用拆分成独立模块,提升了开发效率和灵活性。其核心优势包括技术栈灵活性、独立部署、团队协作及易于维护。文章详细阐述了定义边界、选择框架、管理状态和通信等关键步骤,并讨论了状态同步、样式隔离及安全性等挑战。微前端架构有望成为未来Web开发的重要趋势。
|
1月前
|
JavaScript 前端开发 应用服务中间件
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
140 0
|
1月前
|
存储 前端开发 API
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
92 0
|
2月前
|
前端开发
前端基础(十一)_Float浮动、清除浮动的几种方法
本文介绍了浮动的概念、属性、特性以及清除浮动的几种方法,并通过实例演示了如何使用CSS实现元素的浮动和处理浮动带来的问题。
78 3
|
1月前
|
前端开发
前端常用方法防抖(debounce)和节流(throttle)的示例演示及应用场景说明
前端常用方法防抖(debounce)和节流(throttle)的示例演示及应用场景说明
23 0
|
2月前
|
前端开发 JavaScript
前端ES5 | js —添加元素方法
前端ES5 | js —添加元素方法
|
3月前
|
JavaScript 前端开发 开发者
JS 继承之谜:究竟有哪些神秘方法?Web 前端开发者必知的关键技巧待你揭开谜底!
【8月更文挑战第23天】JavaScript (JS) 是 Web 前端开发的关键语言,其中继承是面向对象编程的重要概念。本文探讨了 JS 中几种继承机制:原型链继承、构造函数继承及组合继承。原型链继承利用原型对象实现属性和方法的共享;构造函数继承通过在子类构造器内调用父类构造器实现私有属性的复制;组合继承结合两者优点,既支持属性共享又避免了属性被意外覆盖的风险。理解这些模式有助于开发者更高效地组织代码结构,提升程序质量。
35 1