• Vue3.0项目——打造企业级音乐App(二)图片懒加载、v-loading指令的开发和优化


    系列文章目录



    图片懒加载

    在这里插入图片描述

    main.js 文件

    • 安装 vue3-lazy,在 main.js 文件中导入并使用
    • 传入两个参数,一个是 lazyPlugin,一个是要加载的图片的相对地址
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import lazyPlugin from 'vue3-lazy'
    
    // 引入全局样式文件
    import '@/assets/scss/index.scss'
    
    createApp(App).use(store).use(router).use(lazyPlugin, {
        loading: require('@/assets/images/default.png')
    }).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    recommend.vue 组件

    • 修改 :srcv-lazy,实现图片的懒加载
    	<div class="icon">
    	    <img width="60" height="60" v-lazy="item.pic">
        </div>
    
    • 1
    • 2
    • 3

    效果图如下:

    在这里插入图片描述

    v-loading 自定义指令开发

    在这里插入图片描述

    ./components/base/loading/loading.vue 组件

    • 该组件定义加载中的图片和文字显示
    <template>
      <div class="loading">
        <div class="loading-content">
          <img width="24" height="24" src="./loading.gif">
          <p class="desc">{{title}}</p>
        </div>
      </div>
    </template>
    
    <script>
      export default {
        name: 'loading',
        data() {
          return {
            title: '正在载入...'
          }
        },
        methods: {
          setTitle(title) {
            this.title = title
          }
        }
      }
    </script>
    
    <style lang="scss" scoped>...</script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    ./components/base/loading/directive.js 文件

    • 该文件自定义 loading 指令
    • 挂载更新的时候做出相应变化
    • 仅适用于 absolute | fixed | relative 的定位(后面还会优化)
    // 自定义指令 loading
    import { createApp } from 'vue'
    import Loading from './loading'
    
    const loadingDirective = {
        mounted(el, binding) {
            const app = createApp(Loading)
            const instance = app.mount(document.createElement('div'))
            el.instance = instance
            if (binding.value) {
                append(el)
            }
        },
        // 更新的时候,loading 为 true,则还是执行 append(el),为 false,执行 remove(el)
        updated (el, binding) {
            if (binding.value !== binding.oldValue) {
                binding.value ? append(el) : remove(el)
            }
        }
    }
    
    function append(el) {
        el.appendChild(el.instance.$el)
    }
    
    function remove(el) {
        el.removeChild(el.instance.$el)
    }
    
    export default loadingDirective
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    main.js 文件

    • 导入并全局使用 loadingDirective
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import lazyPlugin from 'vue3-lazy'
    import loadingDirective from './components/base/loading/directive'
    
    import '@/assets/scss/index.scss'
    
    createApp(App).use(store).use(router).use(lazyPlugin, {
        loading: require('@/assets/images/default.png')
    }).directive('loading', loadingDirective).mount('#app')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ./views/recommend.vue 组件

    • v-loading 绑定加载中
    <div class="recommend" v-loading="loading">
    ...
    	<h1 class="list-title" v-show="!loading">热门歌单推荐</h1>
    </div>
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    v-loading 自定义指令开发的优化

    ./components/base/loading/directive.js 文件

    • 当没有设置 position 为 absolute | fixed | relative 其中一个时,自动添加 position: relative
    // 自定义指令 loading
    import { createApp } from 'vue'
    import Loading from './loading'
    import { addClass, removeClass } from '@/assets/js/dom'
    
    // g-relative 是在 base.sass 中定义好的 position: relative
    const relativeCls = 'g-relative'
    
    const loadingDirective = {
        mounted(el, binding) {
            const app = createApp(Loading)
            const instance = app.mount(document.createElement('div'))
            el.instance = instance
            // 拿到动态参数
            const title = binding.arg
            if (typeof title !== 'undefined') {
                instance.setTitle(title)
            }
    
            if (binding.value) {
                append(el)
            }
        },
        // 更新的时候,loading 为 true,则还是执行 append(el),为 false,执行 remove(el)
        updated (el, binding) {
            const title = binding.arg
            if (typeof title !== 'undefined') {
                el.instance.setTitle(title)
            }
            if (binding.value !== binding.oldValue) {
                binding.value ? append(el) : remove(el)
            }
        }
    }
    
    function append(el) {
        // 获取元素当前样式
        const style = getComputedStyle(el)
        // 如果样式不属于以下三种之一,则给 el 添加需要的定位
        if (['absolute', 'fixed', 'relative'].indexOf(style.position) === -1) {
            // 添加样式
            addClass(el, relativeCls)
        }
        el.appendChild(el.instance.$el)
    }
    
    function remove(el) {
        removeClass(el, relativeCls)
        el.removeChild(el.instance.$el)
    }
    
    export default loadingDirective
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    ./src/js/dom.js 文件

    • 如果没有 absolute | fixed | relative,则添加样式
    • binding.value 为 false 时,移出样式
    export function addClass(el, className) {
      if (!el.classList.contains(className)) {
        el.classList.add(className)
      }
    }
    
    export function removeClass(el, className) {
      el.classList.remove(className)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    recommend.vue 组件

    • 动态获取参数
    <div class="recommend" v-loading:[loadingText]="loading">
    	...
    </div>
    
    data() {
      return {
        loadingText: '正在载入...'
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    至此,推荐页面的基本开发先告一段落,接下来将进行歌手页面的开发

    不积跬步无以至千里 不积小流无以成江海

    点个关注不迷路,持续更新中…

  • 相关阅读:
    【React】React入门
    zabbix(三)————zabbix源码安装及部署
    SpringBoot 2.3.12.RELEASE整合RabittMQ 3.8.12
    centOS7中启动MySQL数据库提示: Failed to start mysqld.service Unit not found
    33、菜谱大全API接口,免费好用
    基于Go语言Iris+Xorm搭建的Web项目框架
    LOGO特训营 第四节 字体设计的重要性
    黑马苍穹外卖7 用户下单+订单支付(微信小程序支付流程图)
    2022-09-09 mysql列存储引擎-POC-需求分析
    web测试点
  • 原文地址:https://blog.csdn.net/qq_45902692/article/details/126342805