让独立 JavaScript 文件与当前 Vue 实例无缝交互的实践

背景

在大型和复杂的业务中,如何让独立的 JavaScript 文件能够轻松地与当前 Vue 实例进行交互是一个关键问题。本文将介绍一种简单而有效的解决方案,以实现 JavaScript 文件与 Vue 实例的无缝交互。我们将以一个示例演示该方案,并展示如何在业务逻辑中灵活应用。

1. 定义 ctx 对象

  • view
    • AxiosView.vue
    • ctx
      • config.js
      • controller.js
      • service.js
      • ctx.js
      • enums.js

首先,我们需要定义一个 ctx 对象,在其中引入各种服务。

javascript 复制代码
// ctx.js
import config from "./config";
import controller from "./controller";
import enums from "./enums";
import service from "./service";

// eslint-disable-next-line no-unused-vars
// let vm = null;

const ctx = {
  init(vmInstance) {
    // vm = vmInstance;
    controller.init(vmInstance);
    service.init(vmInstance);
    enums.init(vmInstance);

    return this;
  },

  controller,
  service,
  config,
  enums,
};

export default ctx;

controller 使用service.js,config.js 中的函数或数据demo(其他js文件与controller.js类似写法)

ini 复制代码
// controller.js

let vm = null;

export default {
  init(vmInstance) {
    vm = vmInstance;
  },

  getMessage() {
    console.log(vm.$data.message); // 组件的实例有一个名为 message 的属性
  },

  setMessage(newMessage) {
    let res = vm.ctx.service.updateMessage();
    vm.$data.message =
      newMessage + " " + res.data + " " + vm.ctx.config.TIME_OUT;
  },

  async getCat() {
    vm.$data.imageUrl = "";

    let params = {
      limit: vm.$data.limit,
    };
    // 使用其他服务
    let res = await vm.ctx.service.getCat(params);
    vm.$data.imageUrl = res[0].url;
  },

  async getDog() {
    vm.$data.imageUrl = "";

    let res = await vm.ctx.service.getDog();
    vm.$data.imageUrl = res.message;
  },
};

2. 在 Vue 实例中引入 ctx 文件

在 Vue 实例中引入 ctx.js 文件,并在 created 钩子中将当前实例传入 ctx.init() 方法。

xml 复制代码
// AxiosView.vue

<template>
  <div>
    <!-- Vue 实例模板内容 -->
  </div>
</template>

<script>
import ctx from "./ctx/ctx";

export default {
  data(){
     return {
        ctx: null
     }
  },
  created() {
    // 在初始化时将当前 Vue 实例传递给 ctx
    this.ctx = Object.freeze(ctx.init(this));
  }
};
</script>

3. 在 Vue 模板中使用 ctx 的服务

现在,我们可以在 Vue 模板中使用 ctx 对象中的服务了。

xml 复制代码
// AxiosView.vue

<template>
  <div>
    <p>{{ message }}</p>
    <select name="" id="">
      <option value="">--Please choose an option--</option>
      <option
        v-for="item in ctx.enums.accountList()"
        :key="item.label"
        :value="item.value"
      >
        {{ item.value }}
      </option>
    </select>

    <div>
      <button @click="ctx.controller.getCat">getCat</button>
      <button @click="ctx.controller.getDog">getDog</button>
    </div>

    <div style="width: 200px; height: 200px; margin: auto">
      <div style="width: 100%; height: 100%; background: #ccc" v-if="!imageUrl">
        loading
      </div>
      <img v-else :src="imageUrl" alt="" style="width: 100%; height: 100%" />
    </div>
  </div>
</template>

<script>
import ctx from "./ctx/ctx";

export default {
  data() {
    return {
      ctx: null,

      message: "Hello, World!",
      limit: 1,
      imageUrl: "",
    };
  },
  created() {
    // 在初始化时将实例传递给 ctx
    this.ctx = Object.freeze(ctx.init(this));
    // ctx.controller.getMessage();
    // ctx.controller.setMessage("Hello, Vue!");
    // ctx.controller.getMessage();
    // console.log(this.ctx.enums.accountList());
  },
};
</script>

结论

通过上述示例,我们展示了如何在 Vue 单文件组件中让独立的 JavaScript 文件能够轻松地与当前 Vue 实例进行交互。这种方案简单易行,同时保持了代码的清晰和可维护性。您可以根据自己的业务需求,灵活地组织和使用 ctx 对象中的各种服务,以实现复杂业务逻辑的开发。

仓库地址:github.com/shouheyuan/...


(TODO)项目案例:

在我的项目中 「项目背景」 「服务拆分」

  • preview-table.vue
    • allocation.js // 收集所有模块数据,使用分配算法得到分配数据,传回实例中渲染
    • batch-edit.js // 批量编辑预览广告数据,编辑后调用分配函数,传回实例中渲染
    • ad-submit.js // 基于实例数据,按接口格式提交
相关推荐
前端付杰21 分钟前
从Vue源码解锁位运算符:提升代码效率的秘诀
前端·javascript·vue.js
用户32035783600223 分钟前
程序员鸡翅-Java微服务从0到1带你做社区项目实战
javascript
一只爱打拳的程序猿28 分钟前
【SpringBoot】实现登录功能
javascript·css·spring boot·mybatis·html5
悬炫1 小时前
闭包、作用域与作用域链:概念与应用
前端·javascript
打野赵怀真1 小时前
前端资源发布路径怎么实现非覆盖式发布(平滑升级)?
前端·javascript
xiejianxin5201 小时前
如何封装axios和取消重复请求
前端·javascript
parade岁月1 小时前
从学习ts的三斜线指令到项目中声明类型的最佳实践
前端·javascript
狼性书生1 小时前
electron + vue3 + vite 渲染进程与渲染进程之间的消息端口通信
前端·javascript·electron
阿里巴巴P8资深技术专家1 小时前
使用vue3.0+electron搭建桌面应用并打包exe
前端·javascript·vue.js
shmily_yyA1 小时前
【2025】Electron 基础一 (目录及主进程解析)
前端·javascript·electron