让独立 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 // 基于实例数据,按接口格式提交
相关推荐
码上暴富13 分钟前
vue2迁移到vite[保姆级教程]
前端·javascript·vue.js
老华带你飞1 小时前
考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)
java·vue.js·spring boot·考研·小程序·毕设·考研论坛平台小程序
伍哥的传说1 小时前
Lodash-es 完整开发指南:ES模块化JavaScript工具库实战教程
大数据·javascript·elasticsearch·lodash-es·javascript工具库·es模块·按需导入
@菜菜_达1 小时前
Lodash方法总结
开发语言·前端·javascript
GISer_Jing1 小时前
低代码拖拽实现与bpmn-js详解
开发语言·javascript·低代码
YAY_tyy1 小时前
基于 Vue3 + VueOffice 的多格式文档预览组件实现(支持 PDF/Word/Excel/PPT)
前端·javascript·vue.js·pdf·word·excel
Yvonne爱编码1 小时前
AJAX入门-AJAX 概念和 axios 使用
前端·javascript·ajax·html·js
Pu_Nine_92 小时前
10 分钟上手 ECharts:从“能跑”到“生产级”的完整踩坑之旅
前端·javascript·echarts·css3·html5
m0_748461394 小时前
Spring Boot + Vue 项目中使用 Redis 分布式锁案例
vue.js·spring boot·redis
li35744 小时前
React 核心 Hook 与冷门技巧:useReducer、useEffect、useRef 及 is 属性全解析
前端·javascript·react.js