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

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

三、其它技巧

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>


目录
相关文章
|
1月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
1月前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
45 5
|
1月前
|
监控 前端开发 jenkins
Jenkins 在前端项目持续部署中的应用,包括其原理、流程以及具体的实现方法
本文深入探讨了Jenkins在前端项目持续部署中的应用,涵盖其基本原理、流程及具体实现方法。首先介绍了Jenkins的基本概念及其在自动化任务中的作用,随后详细解析了从前端代码提交到生产环境部署的全过程,包括构建、测试、部署等关键步骤。最后,强调了持续部署中的代码质量控制、环境一致性、监控预警及安全管理等注意事项,旨在帮助开发者高效、安全地实施持续部署。
65 5
|
2月前
|
存储 前端开发 JavaScript
前端的全栈之路Meteor篇(四):RPC方法注册及调用-更轻量的服务接口提供方式
RPC机制通过前后端的`callAsync`方法实现了高效的数据交互。后端通过`Meteor.methods()`注册方法,支持异步操作;前端使用`callAsync`调用后端方法,代码更简洁、易读。本文详细介绍了Methods注册机制、异步支持及最佳实践。
|
3月前
|
前端开发 JavaScript
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
本文介绍了JavaScript中this的基本使用、this指向的判断以及改变this指向的方法。
55 1
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
|
3月前
|
前端开发
前端基础(十四)_隐藏元素的方法
本文介绍了几种在前端开发中隐藏元素的方法,包括使用`display:none`、`visibility:hidden`、`opacity:0`等CSS属性,并提供了相应的示例代码。此外,还提到了其他隐藏元素的技巧,如通过设置元素位置、使用`overflow`属性和`filter`属性以及`rgba`颜色值来实现元素的隐藏。
71 1
前端基础(十四)_隐藏元素的方法
|
2月前
|
前端开发 JavaScript
掌握微前端架构:构建现代Web应用的新方法
本文介绍了微前端架构的概念及其在现代Web应用开发中的优势与实施方法。微前端架构通过将应用拆分成独立模块,提升了开发效率和灵活性。其核心优势包括技术栈灵活性、独立部署、团队协作及易于维护。文章详细阐述了定义边界、选择框架、管理状态和通信等关键步骤,并讨论了状态同步、样式隔离及安全性等挑战。微前端架构有望成为未来Web开发的重要趋势。
|
3月前
|
前端开发
前端基础(十一)_Float浮动、清除浮动的几种方法
本文介绍了浮动的概念、属性、特性以及清除浮动的几种方法,并通过实例演示了如何使用CSS实现元素的浮动和处理浮动带来的问题。
108 3
|
2月前
|
JavaScript 前端开发 应用服务中间件
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
vue前端开发中,通过vue.config.js配置和nginx配置,实现多个入口文件的实现方法
194 0
|
2月前
|
存储 前端开发 API
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
前端开发中,Web Storage的存储数据的方法localstorage和sessionStorage的使用及区别
127 0