美文网首页
VUE模块目录(main.ts、App.vue、index.ht

VUE模块目录(main.ts、App.vue、index.ht

作者: 大成小栈 | 来源:发表于2024-09-05 22:35 被阅读0次

    VUE工程目录中,一个模块一般包含三个文件:main.ts、App.vue、index.html。

    // main.ts 源码为:
    import Vue from 'vue';
    import App from './App.vue';
    import '@/assets/styles/common.less';
    import { getEnvStatus } from '@/utils/tools';
    import waterfall from 'vue-waterfall2';
    import 'swiper/css/swiper.css';
    import i18n from '@/i18n';
    
    if (getEnvStatus().isRelease) {
      // 阻止vue启动时生成生产提示
      Vue.config.devtools = false;
    } else {
      Vue.config.productionTip = true;
      Vue.config.devtools = true;
    }
    
    Vue.use(waterfall);
    new Vue({
      i18n,
      render: h => h(App)
    }).$mount('#app');
    

    // index.html  源码为:
    <!DOCTYPE html>
    <html lang="">
    
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no,viewport-fit=cover" />
      <meta name="format-detection" content="telephone=no" />
      <meta name="apple-touch-fullscreen" content="yes" />
      <meta name="apple-mobile-web-app-capable" content="yes" />
      <meta name="apple-mobile-web-app-status-bar-style" content="black" />
      <meta name="full-screen" content="yes" />
      <meta name="x5-fullscreen" content="true" />
      <meta name="360-fullscreen" content="true" />
      <title>
      </title>
      <%= htmlWebpackPlugin.options.htmlAppend %>
      <script type="text/javascript" crossorigin="anonymous"
        src="<%= VUE_APP_BASE_URL %>js/toos.js"></script>
    </head>
    
    <body>
      <noscript>
        <strong></strong>
      </noscript>
      <div id="app"></div>
      <!-- 黑白模型 -->
      <script src="<%= VUE_APP_BASE_URL %>js/thsc-theme.min.js"></script>
      <link href="<%= VUE_APP_BASE_URL %>css/thsc-theme-ths.min.css">
      <!-- built files will be auto injected -->
      <script src="<%= VUE_APP_BASE_URL %>js/thsc-base-jssdk.js"></script>
    </body>
    
    </html>
    

    // App.vue 源码为:
    <template>
    
      <div>
        <div v-if="pageType == 0" class="ai-cartoon-page">
            <Launch v-if="showType === AiToolScene.None"
            :title="toolName"
            :slogan="toolSlogan"
            :imgSrc="displayImage"
            @button-clicked="handleSelectPhoto"/>
            <!-- 3D卡通 笑脸特效-->
            <CartoonPage
              v-if="showType === AiToolScene.Cartoon"
              :toolType="toolType"
              :title="toolName"
              :faceImage="selecteFaceImage"
              :imageDataUrlScheme="processImage.imageDataUrlScheme"
              :imageFilePath="processImage.imagePath"
              @next-button-clicked="showResultPage"></CartoonPage>
    
        </div>
        <!-- 结果页 -->
        <Product
          v-if="pageType == 1"
          :resultImage="resultImagePath"
        > </Product>
    
      </div>
    
    </template>
    
    <script lang="ts" setup>
    import Launch from './components/Launch/index.vue';
    import CartoonPage from './components/Cartoon/index.vue';
    import Product from './components/product/index.vue';
    import {ref, onMounted, computed, getCurrentInstance } from 'vue';
    import { AiToolScene } from '@/types/enum';
    import { AIToolModelDetail, AIToolResult, PhotoImage } from './types/model';
    import {
      callNativeFunction,
      getClientUserInfo,
      openPhotoImage,
      setupWebViewJavascriptBridge,
      startSynthesizing
    } from '@/utils/clientBridge';
    import { apiPostRequest } from '@/utils/apiRequest';
    import config from '@/config';
    import { getUserInfo } from "@/constants";
    
    // 获取当前实例
    const { proxy } = getCurrentInstance()!;
    
    const toolSlogan = ref('');
    const pageType = ref(0);
    const toolName = ref('');
    let toolType = ref(AiToolScene.None);
    let showType = ref(AiToolScene.None);
    const processImage = ref();
    const selecteFaceImage = ref('');
    const resultImagePath = ref('');
    let toolDetail: AIToolModelDetail;
    let templateId: string;
    
    
    onMounted( () => {
      const searchParams = new URLSearchParams(window.location.search);
      const toolId = searchParams.get('toolId');
      if (/Android/i.test(navigator.userAgent)) {
        requestDetail(toolId);
      } else {
        // iOS需要独立注册
        setupWebViewJavascriptBridge( () => { 
          requestDetail(toolId);
        });
      }
    });
    
    async function requestDetail(toolId: string) {
      apiPostRequest<AIToolModelDetail>(config.api.getToolDetail, {
          tool_id: toolId,
      }).then(res => {
        toolSlogan.value = res.subtitle;
        toolName.value = res.toolName;
        templateId = res.extParams ? res.extParams.templateId : '';
        toolDetail = res;
      });
    
      const userInfo = await getUserInfo();
      proxy.$i18n.locale = userInfo.language;
      if (/Android/i.test(navigator.userAgent)) {
        const h = userInfo.statusBarHeight ? userInfo.statusBarHeight : 26;
        document.querySelector('.ai-cartoon-page').style.paddingTop = h + "px";
      }
    }
    
    const displayImage = computed(() => {
      const searchParams = new URLSearchParams(window.location.search);
      const paramType = searchParams.get('type');
    
      if (paramType === "cartoon") {
        toolType.value = AiToolScene.Cartoon;
        return "cartoon.png";
      }
      if (paramType === "smile") {
        toolType.value = AiToolScene.Smile;
        return 'smile.webp';
      }
    
      if (paramType === "enhance") {
        toolType.value = AiToolScene.ENHANCE;
        return 'enhance.webp';
      }
    
      return '';
    });
    
    function handleSelectPhoto() {
      startPhotoAsync();
    }
    
    async function startPhotoAsync() {
      try {
        const photoParams = {
          maxSelectCount: 1,
          faceCount: toolDetail.inputConfig.imageConfig.faceMaxCount,
          demoPaths: [toolDetail.cartoonDemoAwsImg],
          userRecentPhoto: true,
          doCrop: false,
          darkMode: true
        }
        const result = await openPhotoImage(photoParams);
        if (result) {
          const selectImage = result.faceImages[0];
          if (toolType.value === AiToolScene.ENHANCE) {
            if (templateId.length > 0) {
            let extParams = toolDetail.extParams;
              const params = {
                animateChannel: "common",
                workName: toolDetail.toolName,
                templateInfo: {
                     play_types: extParams.playTypes,
                     id: extParams.templateId
                },
                imageInfo: {
                  localPath: selectImage.imagePath
                }
              };
              startSynthesizing(params);
            }
            return;
          }
          processImage.value = selectImage;
          selecteFaceImage.value = processImage.value.faceImage;
          showType.value = AiToolScene.Cartoon;
        }
      } catch (error) {
        window.console.error(error);
      }
    }
    
    const showResultPage = (path) => {
      resultImagePath.value = path;
      pageType.value = 1;
    };
    
    </script>
    
    <style lang="less" scoped>
    @import '~@/assets/styles/common.less';
    
    .ai-cartoon-page {
      background-color: #03141A;
      padding-top: env(safe-area-inset-top);
      height: 100vh;
      overflow: hidden;
      font-family: "Poppins";
      background-image: url('~@/assets/images/aitool/bg.png');
      background-size: contain;
      background-position: top;
      background-repeat: no-repeat;
    }
    
    *{
      -webkit-user-select: none; /* Safari */
      -moz-user-select: none;    /* Firefox */
      user-select: none;         /* Non-prefixed version, currently supported by Chrome, Opera and Edge */
      -webkit-touch-callout: none; /* iOS Safari */
    }
    
    </style>
    

    他们三个是什么关系呢?

    在一个典型的 Vue.js 项目中,main.ts、index.html 和 App.vue 这三个文件共同构成了应用的核心结构。

    • index.html:

    这是应用的主 HTML 模板文件。它定义了应用的基本结构,包括 <head> 和 <body> 标签,设置了元信息(如字符集、视口配置等),并在 <body> 中包含一个 id 为 app 的 <div> 元素。
    Vue.js 应用会在这个 <div> 元素中挂载和渲染整个应用的内容。

    • main.ts:

    这是 Vue 应用的入口文件。它是第一个被执行的文件,负责初始化 Vue 实例并将其挂载到 index.html 中的 #app 元素上。
    在 main.ts 中,通常会导入全局的样式、第三方库(如 vue-waterfall2 和 i18n),并配置 Vue 实例(如关闭生产环境提示)。
    最后,它通过 render 函数渲染 App.vue 组件,并将其挂载到 #app 元素。

    • App.vue:

    这是应用的根组件,所有的子组件都将由这个组件管理。App.vue 通常定义了应用的基本布局和逻辑。
    在 main.ts 中被导入,并通过 Vue 实例的 render 函数进行渲染,最终显示在 index.html 的 #app 元素中。

    总结来说,index.html 提供了基础 HTML 结构,main.ts 负责初始化 Vue 应用并将 App.vue 渲染到 index.html 中,App.vue 则定义了应用的核心 UI 和业务逻辑。

    另外,App.vue下面所包含的子模块的代码结构

    App.vue下面所包含的子模块中有一个Launch/index.vue,代码如下:

    <template>
        <div class="flex-start-column">
            
            <TopBar :title="title" :showShare='false' :showMore='false' backgroundColor="transparent"/>
            
            <img :src="imgPath" class="cartoon-image"/>
            <p class="slogan">{{ slogan }}</p>
           
            <button
                class="action-button action-button-gradient" 
                @click="clickSelectPhoto"
                :disabled="slogan.length == 0"
                :style="{opacity: slogan.length == 0 ? '0.5' : '1'}"
            >
                {{ $t('message.pickPhoto') }}
            </button>
            
        </div>
    </template>
    
    <script setup lang="ts">
    import { computed, defineEmits, onMounted, ref } from 'vue';
    import TopBar from '@/components/TopBar/index.vue';
    
    const props = defineProps<{
        slogan: string
        imgSrc: string
        title: string
    }>()
    
    const emit = defineEmits<{
        (event: 'button-clicked'): void;
    }>();
    
    const imgPath = computed(() => {
        return require("@/assets/images/aitool/" + props.imgSrc);
    });
    
    const clickSelectPhoto = () => {
        emit('button-clicked');
    }
    
    </script>
    
    <style scoped lang="less">
    @import '~@/assets/styles/common.less';
    
    .flex-start-column {
        display: flex;
        justify-content: start;
        flex-direction: column;
        align-items: center;
      }
    
    .cartoon-image {
        width: calc(100% - 96px);
        height: auto;
        aspect-ratio: 1/1;
        margin: 64px 48px 0px;
        border-radius: 16px;
        object-fit: cover;
    }
    
    .slogan {
        margin-top: 32px;
        font-size: 18px;
        font-weight: 500;
        height: 27px;
        color: #FFFFFF;
    }
    
    .action-button {
        height: 54px;
        margin: 35px 67px;
        width: calc(100% - 134px);
        border-radius: 27px;
        color: white;
        border: none;
        font-size: 18px;
        font-weight: 600;
        text-align: center;
        flex-grow: 1;
    }
    
    // 普通用户渐变背景
    .action-button-gradient {
        background: linear-gradient(to right, #00CCBB, #00E586);
    }
    // VIP背景
    .action-button-gradient-pro {
        background: linear-gradient(to right, #18EE92, #2FC4D9, #3D7CFF);
    }
    
    </style>
    

    大致分为三个大部分:<template>、<script setup lang="ts">、<style scoped lang="less">,其中<script>内的方法可以互调,最后<script>、<style>都会被<template>统一调用。

    相关文章

      网友评论

          本文标题:VUE模块目录(main.ts、App.vue、index.ht

          本文链接:https://www.haomeiwen.com/subject/pksdljtx.html