惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
云风的 BLOG
云风的 BLOG
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Recent Announcements
Recent Announcements
IT之家
IT之家
Google DeepMind News
Google DeepMind News
罗磊的独立博客
爱范儿
爱范儿
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
U
Unit 42
MongoDB | Blog
MongoDB | Blog
S
SegmentFault 最新的问题
B
Blog
博客园 - 叶小钗
月光博客
月光博客
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
C
Check Point Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

博客园 - 小虫1

不用高配显卡实现 AI 提高视频分辨率|麻雀 AI 视频修复器实测对比 Topaz Video AI AI 提高视频分辨率新选择|麻雀 AI 视频修复器 vs Topaz,无高端显卡也能做视频超分 麻雀 AI 工具箱视频去水印技术解析:AI 视频去水印核心能力如何在网页端落地 麻雀 AI 工具箱视频去水印实战体验:开发者视角下的 AI 视频去水印避坑指南 麻雀 AI 工具箱视频去水印横评:三款 AI 视频去水印方案深度对比 麻雀 AI 工具箱视频去水印技术拆解:多框选与关键帧跟踪,网页端也能搞定动态水印 三款本地视频去水印工具技术向对比:VSR、HitPaw 与妙妙水印助手实测 敏感开发素材处理:三类视频工具的隐私安全技术对比 开发素材处理效率指南:三种视频画质提升方案实测与选型 浏览器端 AI 视频修复技术浅析:三类本地处理方案的实现原理与实测 AI 视频修复技术落地对比:四款去水印工具的技术路线解析 浏览器端本地视频处理实测:4 种去水印方案的技术原理与效果对比 前端开发者视角:一个视频去水印工具的技术猜想 记一次本地视频去水印踩坑经历——从本地部署到在线工具 前端实现视频去水印的几种技术方案对比 豆包视频去水印工具横向测评:麻雀 AI 工具箱与 3 款海外工具实测对比 视频去水印工具实战横评:少谈“黑科技”,多聊实际能用的 2026 在线视频去水印工具实测:4 种方案对比,本地处理首选麻雀AI工具箱 豆包生成的图片,怎么去水印? 2026年,GEO到底怎么做?-麻雀GEO Topaz Video AI的替代品 -麻雀AI视频修复工具,免费、安全、高效的Topaz替代选择 视频清晰度增强网站-麻雀AI视频修复工具 跟框架无关的前端换皮肤 前端请求跨域,解决方案 ssh2-sftp-client 上传文件至服务器 vue项目下自己封装上传文件功能 beego 注册路由失效404,commentsRouter.go没有生成 前端代码实现整体缩放网页,做到缩放分辨率的效果 前端 docker jenkins mkdocs生成的网站为何很慢
vue2 函数式调用一个弹框组件
小虫1 · 2022-04-26 · via 博客园 - 小虫1

注册为组件的方式,做个弹框很容易。但是用过ant design vue 等框架,你会发现人家的弹框都是通过函数调用的,类似于这样:

this.$confirm({
            content: 'destroy all',
            onOk() {
              return new Promise((resolve, reject) => {
                setTimeout(Math.random() > 0.5 ? resolve : reject, 1000);
              }).catch(() => console.log('Oops errors!'));
            },
            cancelText: 'Click to destroy all',
            onCancel() {
              self.destroyAll();
            },
});

并且弹出后,在body底部,并不在业务的html中。

这个可以这么做的思路:做一个vue实例,把他挂载到body上。下面直接上代码:

src/components/Modal/index.vue

<template>
  <div class="mask" v-show="visiable" @click="cancel">
    <div class="modal" @click.stop="() => {}">
      <h2>{{ title }}</h2>
      <div class="content" v-html="content"></div>
      <footer>
        <div class="btn" @click="cancel">取消</div>
        <div class="btn" @click="ok">确定</div>
      </footer>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: "",
    },
    content: {
      type: String,
      default: "",
    },
    onCancel: {
      type: Function,
      default: () => {},
    },
    onOk: {
      type: Function,
      default: () => {},
    },
  },
  data() {
    return {
      visiable: false,
    };
  },
  methods: {
    open() {
      this.visiable = true;
    },
    cancel() {
      this.onCancel();
      this.visiable = false;
    },
    ok() {
      this.onOk();
      this.visiable = false;
    },
  },
};
</script>

<style lang="less" scoped>
.mask {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  z-index: 10000;
  background-color: rgba(0, 0, 0, 0.55);
}
.modal {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 600px;
  padding: 0 34px;
  background-color: #fff;
  border-radius: var(--btn-radius);
  h2 {
    height: 80px;
    font-size: 20px;
    font-family: PingFangSC-Medium, PingFang SC;
    font-weight: 500;
    color: #272727;
    line-height: 80px;
    border-bottom: 1px dashed rgba(151, 151, 151, 0.2);
  }
  .content {
    font-size: 16px;
    margin: 36px 0 50px;
  }
  footer {
    display: flex;
    justify-content: space-between;
    margin-bottom: 50px;
    .btn {
      width: 180px;
      height: 44px;
      border-radius: 2px;
      border: 1px solid rgba(102, 102, 102, 0.7);
      text-align: center;
      line-height: 44px;
      cursor: pointer;
      &:last-child {
        background: var(--btn-bg);
        color: #fff;
      }
    }
  }

  /deep/.price-num {
    font-size: 20px;
    font-family: PingFangSC-Medium, PingFang SC;
    font-weight: 500;
    color: var(--text-1);
  }
}
</style>

  src/components/Modal/index.js(核心代码)

import Vue from "vue";
import Modal from "./Index.vue"; // 引入弹窗组件

const ModalComponent = Vue.extend(Modal);
let app;
Modal.open = (options) => {
	if (options === 'cancel') {
		app && app.cancel();
		return;
	}
	app = new ModalComponent(
		{ propsData: options }
	).$mount();
	document.body.appendChild(app.$el);
	Vue.nextTick(() => {
		app.open();
	});
};

export default Modal; // 导出

  main.js

import $modal from '@/components/modal/index.js'
Vue.prototype.$modal = $modal.open;

组件里调用举例:

  this.$modal({
        title: "再租一台",
        content: "租用和目标机器,配置相同的一台机器,可选择GPU数量",
        onOk: () => {
          this.$router.push({
            path: "/store/hire",
            query: {
              gpuType: cObj.Gpu_type,
              node: "全部",
              mirrorImage: cObj.Image,
              mirrorImageLabel: cObj.Image,
              dateNum:
                cObj.Use_mode === 0
                  ? 0
                  : Math.round((cObj.Due_time - cObj.Ctime) / 24 / 3600),
              gpuNum: cObj.Gpu_num,
              os: cObj.ContainerType.includes("kvm") ? "kvm" : "docker",
              performance: cObj.Performance,
            },
          });
        },
      });

优化,vue是个单页面应用SPA。在路由变化时,应该隐藏弹框:

router.beforeEach(async (to, from, next) => {
     Vue.prototype.$modal('cancel');
})