节流、防抖
函数节流(throttle):
高频率触发的事件,在指定的单位时间内,只响应第一次(前面触发的执行前,忽略后面的事件)
函数防抖(debounce):
在一段时间内,只响应最后一次,如果在指定时间触发,则重新计算时间(后面触发的事件执行,替代了前面的事件)
函数节流(throttle)与 函数防抖(debounce)
都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。
节流
// 我们可以知道这里 fun.apply(this,arguments)的用意,无非就是想fun中的this指向debounce中return的这个函数中的this,return回来的这个函数中的this也就是指向直接调用return 函数那个对象。
function throttle(fn,time){
let canRun = true;
return function(){
if(!canRun) return
canRun = false;
setTimeout(()=>{
fn.apply(this,arguments)
canRun = true
},time)
}
}
function sayHi(e){
console.log(e.target.innerWidth,e.target.innerHeight)
}
window.addEventListener('resize',throttle(sayHi,500))
防抖
function debounce(fn,time){
let timeout = null
return function(){
clearTimeout(timeout)
timeout = setTimeout(()=>{
fn.apply(this,arguments)
},time)
}
}
funnction sayhi(){
console.log('防抖成功')
}
var inp = document.getElementById('inp')
inp.addEventListener('input' , debounce(sayHi,5000))
filter过滤器
过滤器分为两种
- 组件内的过滤器(组件内有效)
- 全局过滤器(所有组件共享)
{{message | filterA | filterB}}
上述表示:message是作为参数传给filterA, 而filterA返回值作为参数传给filterB,最终结果显示由filterB返回。
局部过滤器
格式化时间或日期,补全指定位数,不足个位数补0
// filter/index.js文件
export default {
dateFormat: value => {
const dt = new Date(value * 1000)
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + '').padStart(2, '0') // .padStart(指定位数,"要补全的符号或值")
const d = (dt.getDay() + '').padStart(2, '0')
const hh = (dt.getHours() + '').padStart(2, '0')
const mm = (dt.getMinutes() + '').padStart(2, '0')
const ss = (dt.getSeconds() + '').padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
}
// 在 .vue 文件中使用局部过滤器
<script>
import filters from '../filter'
export default {
... ...
filters: { ...filters },
data() {
return {}
}
}
</script>
<div> 日期:{{ date | dateFormat }} </div>
全局过滤器
通用字典项的回显:比如性别男女或通用选择是否,后端传给我们的数据是0、1,我们需要在页面上显示男女或是否
// constants/dictionary.js 文件
export const GENDER_MENU = [
{ code: 0, label: '男'},
{ code: 1, label: '女'}
];
export const COMMON_MENU = [
{ code: 0, label: '否'},
{ code: 1, label: '是'}
];
export default {
GENDER_MENU, COMMON_MENU
}
// filter/dict.js 文件
import Dict from '../constants/dictionary'
export const genderMenu = {
func: value => {
const target = Dict.GENDER_MENU.filter(item => {
return item.code = value;
})
return target.length ? target[0].label : value;
}
}
export const commonMenu = {
func: value => {
const target = Dict.COMMON_MENU.filter(item => {
return item.code = value;
})
return target.length ? target[0].label : value;
}
}
// filter/index.js 文件
import * as filters from './dict' // 导入过滤函数
const Install = Vue => {
// 导入的 filters 是一个对象,使用Object.keys()方法,得到一个由key组成的数组,遍历数据,让key作为全局过滤器的名字,后边的是key对应的处理函数,这样在任何一个组件中都可以使用全局过滤器了
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key].func)
})
}
export default Install
// main.js 文件
... ...
import filters from './../filter/index'
Vue.use(filters)
... ...
// .vue 文件中使用全局过滤器
<p>性别:{{ gender | genderMenu }}</p>
slot插槽的用法
-
单个插槽
<div id="app">
<child-component>
<p>来自父组件的问候</p> // 这看似是在子组件中写的内容,但其实这是属于父组件的作用域
</child-component> // 也就是说,其实这个 p元素 ,是父组件中的内容
</div>
Vue.component('child-component', {
template: `<div>
<slot></slot> // 在子组件中使用 slot 元素
</div>`
})
- 具名插槽
<div id="app">
<child-component>
<p>离离原上草,</p>
<p>一岁一枯荣。</p>
<p>野火烧不尽,</p>
<p>春风吹又生。</p> // 上面的四个 p 元素没名字?
<address slot="footer">白居易</address> // 用 slot 起名字
<h2 slot="header">赋得古原草送别</h2> // 用 slot 起名字
</child-component>
</div>
Vue.component('child-component', {
template: `<div>
<slot name="header"></slot> // 有 name
<slot></slot> // 没有 name ?这个先放着,后面再说
<slot name="footer"></slot> // 有 name
</div>`
})
- 作用域插槽
上面说的单个插槽和具名插槽,都是父组件向子组件传递数据。那么,父组件要从子组件中获取数据,怎么办呢?同样,使用 slot 就可以办到。
<div id="app">
<child-component>
<template slot="text1" slot-scope="data"> // 这里用的 template
{{ data.text }}
</template>
<p slot="text2" slot-scope="data"> // 这里用的 p
{{ data.text }}
</p>
</child-component>
</div>
Vue.component('child-component', {
template: `<div>
<slot name="text1" text="我多想再见你,哪怕匆匆一眼就别离"></slot>
<slot name="text2" text="路灯下昏黄的剪影,越走越漫长的林径"></slot>
</div>`
})
var app = new Vue({
el: '#app',
data: {}
})
- 访问插槽
如果有多个插槽,我们访问插槽的时候,就要用到 this.$slots
<div id="app">
<child-component>
<p>离离原上草</p>
<p>一岁一枯荣</p>
<p>野火烧不尽</p>
<p>春风吹又生</p>
<address slot="footer">白居易</address>
<h2 slot="header">赋得古原草送别</h2>
</child-component>
</div>
Vue.component('child-component', {
template: `<div>
<slot name="header"></slot>
<slot name="footer"></slot>
<slot></slot>
</div>`,
mounted: function () {
let header = this.$slots.header // 访问名字为 header 的插槽
let footer = this.$slots.footer // 访问名字为 footer 的插槽
let headerText = header[0].elm.innerText // header 中的元素的文本
let footerText = footer[0].elm.innerText // footer 中的元素的文本
console.log(headerText)
console.log(footerText)
}
})
var app = new Vue({
el: '#app',
data: {}
})