使用事件代理实现vue的手风琴组件

在项目中要做一个手风琴组件,需求是页面created事件中请求数据,以显示在列表中,加载数据时显示“正在加载”,没有数据了就显示“没有更多数据了”,当点击列表项时再去请求相应的详情,如果给每一个li绑定相应的事件处理程序,在JavaScript中,添加到页面上的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断的与dom节点进行交互,访问dom的次数越多,引起浏览器重绘与重排的次数也就越多,就会延长整个页面的交互就绪时间,这就是为什么性能优化的主要思想之一就是减少DOM操作的原因;如果要用事件委托,就会将所有的操作放到js程序里面,与dom的操作就只需要交互一次,这样就能大大的减少与dom的交互次数,提高性能;每一个函数都是一个对象,是对象就会占用内存,所以有很多个li就会导致内存占用率大,性能也会越来越差,所以我们在此使用事件代理来执行事件。

2.什么是事件代理 ?

事件代理是根据事件冒泡原理来实现的,事件冒泡即从事件的最深节点开始 ,然后逐步向上传播事件,比如给一个对象绑定了oncllick事件,如果此对象上没有绑定onclick事件就会向此对象的父元素传播,从里到外,直至它被处理(父级对象所有同类事件也会被激活),所以如果我们给父元素绑定事件,那么给里边的子元素即嵌套子元素做onclick事件后,都会冒泡到最外层的父元素上,都会被触发 ,这就是事件委托,委托它们父级代为执行事件。

在此组件中,我们要将li的点击事件绑定给ul,实现加载对应详情项。

3.代码实现

// html:

    // 列表

  • {{item.ctime}}

    {{item.total_interest}}元

    // 列表详情项

    ...

    // js:

    // 引入弹框组件

    import * as iakit from 'iakit'

    // 引入请求接口

    import { queryInterestListInfo, interestDetailInfo } from 'services'

    // 引入判断是否是页面底部函数

    import isReachBottom from 'helper/isReachBottom'

    export default create({

    data() {

    return {

    //此处数据为在页面上显示的数据

    listData: [],

    detailInfo: [],

    current: {

    basic: {},

    newcomer: [],

    new_come_rate: '',

    activity: [],

    commission: []

    },

    rate: 0,

    page: 1,

    // 是否有更多数据

    hasMore: true,

    // 是否显示加载更多数据信息

    isShowLoading: true

    }

    },

    created() {

    this.queryInterestList()

    // 为窗体添加滚动事件 RreachBottom,判断是否滑动到了页面底部

    window.addEventListener('scroll', this.RreachBottom)

    },

    methods: {

    // 找到li子节点

    getNode(node) {

    if (node.nodeName === 'LI') {

    return node

    } else if (node.nodeName === 'UL') {

    return false

    } else {

    return this.getNode(node.parentNode)

    }

    },

    toggle(e) {

    var target = e.target || e.srcElement

    var $li = document.querySelectorAll('li')

    // thisLi 当前点击li的e.target

    var thisLi = this.getNode(target)

    // 获取所有列表项,生成数组

    var $details = document.querySelectorAll('.earnDetail')

    // 获取所有旋转图标,生成数组

    var $icons = document.querySelectorAll('.eranIcon')

    for (let i = 0, length = $li.length; i < length; i++) {

    if (thisLi === $li[i]) {

    if ($details[i].style.display === '') {

    // div展开时,将它隐藏

    $details[i].style.display = 'none'

    $icons[i].className = 'eranIcon'

    } else {

    // 隐藏时,将它展开

    // 如果当前详情项数组里无对应此项数据

    if (!this.detailInfo[i]) {

    let ctime = thisLi.children[0].children[0].innerHTML

    interestDetailInfo(

    {

    'data': ctime

    }

    ).then((resp) => {

    // 将请求到的详情项放入详情数组中

    this.detailInfo[i] = resp

    // 将请求详情项赋值给当前详情项,以供显示

    this.current = resp

    if (!this.activity) {

    this.rate = 0

    } else {

    this.rate = this.activity.rate

    }

    }).catch((err) => {

    iakit.alert('', err.message, [

    {

    text: '朕知道了'

    }

    ])

    })

    } else {

    // 如果详情项数组中有对应此项数据,就将数组中的数据赋值给当前详情项,以供显示

    this.current = this.detailInfo[i]

    }

    $details[i].style.display = ''

    $icons[i].className = 'eranIcon rotate'

    }

    } else {

    $details[i].style.display = 'none'

    $icons[i].className = 'eranIcon'

    }

    }

    },

    queryInterestList() {

    // 判断数据是否正在加载中,以防重复加载

    if (this.fetching) {

    return

    }

    this.fetching = true

    this.isShowLoading = true

    this.loadingTip = '正在加载中...'

    queryInterestListInfo({

    page: this.page,

    len: 15

    }).then((resp) => {

    const data = resp.list

    // 成功后不显示提示信息,数据加载完毕

    this.isShowLoading = false

    this.fetching = false

    if (data && data.length > 0) { // 存在数据,用concat连接每次请求的数组项

    this.listData = this.listData.concat(data)

    } else { // 没有更多数据了

    this.hasMore = false

    this.isShowLoading = true

    this.loadingTip = '没有更多数据了'

    }

    // 请求页标志加1,即当再次请求时请求下一页

    this.page += 1

    }).catch((err) => {

    this.fetching = false

    iakit.alert('', err.message, [

    {

    text: '朕知道了'

    }

    ])

    })

    },

    RreachBottom() {

    // 如果滚动到页面底部,并且当前选项卡为投资项

    if (isReachBottom()) {

    // 判断接口还有无数据 ,如果有,就再次请求接口

    if (this.hasMore) {

    this.queryInterestList()

    } else {

    // 如果没有数据,就解绑此事件

    window.onscroll = null

    }

    }

    }

    }

    })

    数据加载中

    列表详情项

    没有更多数据了

  • 最后编辑于
    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 199,440评论 5 467
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 83,814评论 2 376
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 146,427评论 0 330
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 53,710评论 1 270
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 62,625评论 5 359
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 48,014评论 1 275
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 37,511评论 3 390
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 36,162评论 0 254
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 40,311评论 1 294
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 35,262评论 2 317
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 37,278评论 1 328
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 32,989评论 3 316
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 38,583评论 3 303
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 29,664评论 0 19
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 30,904评论 1 255
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 42,274评论 2 345
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 41,856评论 2 339

    推荐阅读更多精彩内容

    • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
      卡卡罗2017阅读 134,561评论 18 139
    • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
      passiontim阅读 171,259评论 25 707
    • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
      小菜c阅读 6,335评论 0 17
    • 忙忙碌碌 心累 编辑微博微博 报告报告 一个月一个月的循环 不知道意义为何 似乎更多是快速化下的追逐 很累了 睡觉...
      元气满满的慧慧酱阅读 150评论 0 0
    • 一、三大理论观点 古典理性理论观点 权变理论观点 组织行为理论观点 二、 八大学派 三、知识管理的主要模型 知识管...
      淼帅校长学习力阅读 986评论 0 0