让独立 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 // 基于实例数据,按接口格式提交
相关推荐
VXbishe1 小时前
【课程设计】基于SpringBoot的乡村政务服务系统的设计与实现-计算机毕设77011
javascript·vue.js·spring boot·python·php·课程设计·政务
志尊宝1 小时前
Vue3 零基础每日笔记(037):动手封装 useMouse 与 useWindowSize——事件监听的标准模板
前端·javascript·vue.js·笔记·html5
shmily麻瓜小菜鸡1 小时前
TDD(测试驱动开发)详解
开发语言·javascript·typescript·node.js·ecmascript
BillKu2 小时前
vue3双向邦定:使用defineModel替换defineProps+defineEmits
vue.js
wcy03103 小时前
POST为什么会发送两次请求
javascript·ajax
志尊宝3 小时前
Vue3 零基础每日笔记(047):动态路由与路由参数——:id 传参、query 传参、props 解耦
前端·javascript·vue.js·笔记·html5
计算机毕设定制辅导-无忧学长3 小时前
《基于SpringBoot的中学教师数字胜任力测评网站的设计与实现》
java·vue.js·spring boot·mysql·中学教师数字胜任力测评网站
flash俊杰6 小时前
Vue 3 响应式陷阱与状态单例:从 TDZ 白屏到跨进程 Proxy 剥离
vue.js
志尊宝6 小时前
Vue3 零基础每日笔记(046):声明式导航与编程式导航——useRouter / useRoute 双子星
vue.js·笔记·#vue #前端 #前端开发·#javascript·#vue.js
朝屯暮蒙vi7 小时前
随记:h5+中uploader不能添加参数数据,要通过task
javascript