Implementación de depuración de vista previa rápida para desarrollo móvil

Las leyes se crean y se descubren, y la memoria es la derivación y extracción de leyes.

antecedentes

Cuando estaba trabajando en el proyecto del terminal móvil vue2, hice una función de vista previa de código de escaneo rápido en el terminal móvil. Fue muy útil en la etapa de depuración, así que quería moverlo al proyecto vue3. Pensé que era muy simple. , pero me encontré con varios problemas. me atascó durante mucho tiempo

  1. Introducción de variables globales
  2. directiva personalizada
  3. Las instrucciones de createApp no ​​se comparten (las instrucciones deben haberse montado en el elemento al renderizar)

necesitar

Al desarrollar en el lado web, si desea ver rápidamente el efecto en el lado del teléfono móvil, escanear el código y abrirlo en el lado del navegador es la opción más conveniente. Al mismo tiempo, si desea obtener una vista previa en la aplicación, se proporciona la función de copia y la vista previa de sincronización de la vista web se realiza a través de la función de lectura y pegado de contenido + salto de esquema de la aplicación.

Realizar ideas

  1. Use hmr para sincronizar la página de depuración de la misma ip
  2. Obtenga dinámicamente la IP nativa en la etapa de desarrollo e inyéctela en el entorno de desarrollo
  3. Cree el componente, genere dinámicamente la URL de depuración correspondiente según la IP, genere el código QR correspondiente y copie el contenido
  4. Determinar si mostrar el componente enrutando el parámetro de consulta

lograr

Use hmr para sincronizar la página de depuración de la misma ip

Tanto webpack como vite proporcionan la función hmr

Obtenga dinámicamente la IP nativa en la etapa de desarrollo e inyéctela en el entorno de desarrollo

nodejs puede obtener fácilmente la IP nativa:

const os = require("os");
function GetIp() {
  let ifaces = os.networkInterfaces();
  for (let i in ifaces) {
    for (let j in ifaces[i]) {
      let alias = ifaces[i][j];
      if (
        alias.family === "IPv4" &&
        alias.address !== "127.0.0.1" &&
        !alias.internal
      ) {
        return alias.address;
      }
    }
  }
}
export default GetIp()
复制代码

Después de obtener la ip, el paquete web la inyecta a través de process.env

new webpack.DefinePlugin({
      'process.env': {IP: GetIp()}
  })
复制代码

vite se inyecta a través de define

  define: {
    VITE_DEV_IP: JSON.stringify(GetIp())
  }
复制代码

construir componentes

Aquí solo se muestran los componentes de vue3

<style lang="less" scoped>
.dev-code {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  right: 0;
  background-color: #ffffff;
  .tips {
    font-size: 0.18rem;
    color: #000;
    margin: 0.1rem 0;
    text-align: center;
  }
  .close-btn {
    width: 0.4rem;
    height: 0.4rem;
    position: absolute;
    left: 0;
    right: 0;
    bottom: -0.5rem;
    margin: auto;
    img {
      width: 100%;
      height: 100%;
    }
  }
}
</style>
<template>
  <Teleport to="body">
    <section
      class="dev-code"
      v-show="visible == true"
      v-clipboard:copy="url"
      v-clipboard:success="Tip"
    >
      <qrcode :value="url" id="qrcode" />
      <div class="tips">扫码手机联调</div>
      <div class="tips">点击复制链接</div>
      <a href="javascript:;" class="close-btn" @click.stop="visible = false">
        <img src="https://xxxcdn.xxx.cn/common/close-grey.png" />
      </a>
    </section>
  </Teleport>
</template>
<script lang="ts" setup>
// 调试用二维码
import qrcode from "../qrcode.vue";
import { ref } from "vue";
import { toast } from "../toast/useToast";
defineProps({
  url: {
    type: String,
    // 这里vite通过define定义的全局变量会注入到window对象上,所以命名要独特
    default: `${location.protocol}//${window.VITE_DEV_IP}:${location.port}${location.pathname
      }${location.search.replace("debug=1", "")}`,
  },
});
const visible = ref(true);
function Tip() {
  toast("已成功复制,去浏览器打开吧,注意要和电脑在同一局域网哦~");
}
</script>

// 构建渲染函数
import { mountComponent } from "../../lib/utils/mount-component";
import devCodeConstructor from "./devCode.vue";
const debug = () => {
  return mountComponent(devCodeConstructor);
};
export default debug;
复制代码

La función de representación puede referirse aPublicación anterior

Determinar si mostrar el componente enrutando el parámetro de consulta

Agregue un interceptor al enrutador y muestre el componente cuando se lea el parámetro de consulta especificado en el entorno de desarrollo

router.afterEach((to, from) => {
  if (import.meta.env.MODE === 'development' 
  && !!to.query.debug 
  && +to.query.debug === 1) {
    debug();
  }
});
复制代码

pregunta

Introducción de variables globales

Anteriormente, webpack usaba DefinePlugin para inyectar process.env para lograr

El nuevo marco usa vite, vite también proporciona la función de inyección de variables globales, principalmente usando dotenv para cargar variables de entorno adicionales desde archivos en su directorio de entorno, pero los archivos dotenv son estáticos, no quiero que otros desarrolladores tengan que verificar la ip y escríbalo usted mismo, encontrará las opciones de definición e inyectará variables dinámicas en el objeto de la ventana, pero este método debe prestar atención, los datos inyectados deben ser la cadena deserializada por Json.stringify, y la propia cadena debe invertirse .Serializalo , todo es por flojera ^_^

Las variables globales inyectadas por dotenv se pueden obtener a través de import.meta.env.development.xxx, puede参考官方文档, define options 也可以参考官方文档

自定义指令

自定义指令主要为了实现复制功能,可以参考我之前的一篇文章

createApp的指令不共用(render的时候指令要已经挂载到元素上)

新的createApp不会公用其他createApp实例的指令,于是对之前的方法做了一个扩展:

import { Component, createApp } from "vue";
import DirectiveExtensions from "../../directive";
export function mountComponent(rootComponent: Component) {
  // 添加自定义 指令
  const app = createApp(rootComponent).use(DirectiveExtensions);
  const root = document.createElement("div");
  document.body.appendChild(root);
  return {
    instance: app.mount(root),
    unmount() {
      app.unmount();
      document.body.removeChild(root);
    },
  };
}
复制代码

实现效果

微信图片_20220325175222.png

Supongo que te gusta

Origin juejin.im/post/7078981127435714596
Recomendado
Clasificación