zoukankan      html  css  js  c++  java
  • 自定义v-loading指令

    1. Loading组件

    <template>
      <div>
        <van-loading :color="loadingList.color" vertical>{{ loadingList.title }}</van-loading>
        <div class="mask" v-bind:class="{ 'bottom-mask': loadingList.isBottomMask }"></div>
      </div>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, toRefs } from 'vue'
    
    interface State {
      loadingList: {
        title: string
        color: string
        isBottomMask: boolean
      }
    }
    
    export default defineComponent({
      name: 'Loading',
      setup() {
        const state = reactive<State>({
          loadingList: {
            title: '加载中...', //提示信息
            color: '#c9c9c9', //加载颜色
            isBottomMask: false //是否遮住页面,只显示返回
          }
        })
    
        const setLoading = (val: any) => {
          state.loadingList = { ...state.loadingList, ...val }
        }
        return {
          ...toRefs(state),
          setLoading
        }
      }
    })
    </script>
    
    <style lang="scss" scoped>
    @import '@/style/variables.scss';
    .van-loading {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 10;
    }
    // 遮罩层
    .mask {
       100%;
      height: calc(100% - 138px);
      background-color: transparent;
      position: fixed;
      top: 88px;
      left: 0;
      z-index: 1;
    }
    .bottom-mask {
      height: calc(100% - 88px);
      background-color: $background-color-base;
    }
    </style>
    
    

    2. directives文件夹下 loading.ts 指令ts

    import LoadingComponent from '@/components/Loading.vue'
    import { createApp } from 'vue'
    import { Loading } from 'vant'
    
    const loading = {
      mounted(el: any, binding: any) {
        // 创建app对象 根组件为我们写好的 loading 组件
        const loading = createApp(LoadingComponent)
        //引入vant组件
        loading.component(Loading.name, Loading)
        //动态创建一个div节点,将app挂载在div上
        const instance = loading.mount(document.createElement('div'))
        // 因为在updated也需要用到 instance 所以将 instance 添加在el上 ,在updated中通过el.instance 可访问到
        el.instance = instance
        // v-loading传过来的值储存在 binding.value 中
        if (binding.value?.isLoading) {
          el.instance.setLoading(binding.value) //setLoading是LoadingComponent组件的方法,用回调传参
          add(el)
        }
      },
    
      updated(el: any, binding: any) {
        // 如果value的值有改变,那么我们去判断进行操作
        if (binding.value?.isLoading !== binding.oldValue?.isLoading) {
          el.instance.setLoading(binding.value)
          binding.value?.isLoading ? add(el) : remove(el)
        }
      }
    }
    
    // const className = 'loading-relative' // loading-relative 是我在全局写的样式名 {position:relative}
    function add(el: any) {
      // const style = getComputedStyle(el)
      // if (['absolute', 'relative', 'fixed'].indexOf(style.position) === -1) {
      //   el.classList.add(className) // 通过此API可以添加类名
      // }
      //向el节点插入动态创建的 div 节点 , 内容就是我们的 loading 组件
      el.appendChild(el.instance.$el)
    }
    
    function remove(el: any) {
      //移除动态创建的 div 节点
      el.removeChild(el.instance.$el)
    }
    
    export default loading
    
    

    3. main.ts

    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'
    import store from './store'
    import 'amfe-flexible'
    import '@/style/index.scss'
    import SvgIcon from './components/SvgIcon.vue'
    import Vconsole from 'vconsole'
    import loading from './directives/loading'
    
    // 不同浏览器一些默认的html标签的展示行为是不一致的,normalize.css 使样式在所有浏览器上保持一致
    import 'normalize.css'
    
    import { components } from './plugins/vant'
    process.env.VUE_APP_MODE !== 'production' && new Vconsole()
    
    const app = createApp(App)
    components.forEach(component => {
      app.component(component.name, component)
    })
    app.component('svg-icon', SvgIcon)
    app.use(store).use(router).directive('loading', loading).mount('#app')
    
    

    4. 组件页面调用

    <template>
      <div
        v-loading="{
          isLoading: loadingList.isLoading,
          title: loadingList.title,
          isBottomMask: loadingList.isBottomMask,
        }"
      ></div>
    </template>
    
    <script lang="ts">
    import { defineComponent, reactive, toRefs } from "vue";
    
    interface LoadingList {
      isLoading: boolean;
      title: string;
      isBottomMask: boolean;
    }
    
    const loadingList: LoadingList = {
      isLoading: false,
      title: "加载中...",
      isBottomMask: false,
    };
    
    export default defineComponent({
      name: "Receipt",
      setup() {
        const state = reactive({
          loadingList,
        });
    
        return {
          ...toRefs(state),
        };
      },
    });
    </script>
    
    <style lang="scss" scoped>
    </style>
    
    
  • 相关阅读:
    【HDU5015】233 Matrix
    【POJ3233】Matrix Power Series
    【POJ3070】Fibonacci
    【NOIP模拟】奇怪的字符串
    【NOIP模拟】超级跳棋
    【NOIP模拟】玛雅文字
    【NOIP模拟】距离
    【闲聊】关于本BLOG
    【NOIP模拟】树
    【NOIP模拟】机器人
  • 原文地址:https://www.cnblogs.com/xm0328/p/15248240.html
Copyright © 2011-2022 走看看