首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >onMount被叫了两次

onMount被叫了两次
EN

Stack Overflow用户
提问于 2022-03-31 22:37:22
回答 1查看 1K关注 0票数 1

我有一个布局页面,每个组件都继承它。我的问题是对每个组件调用两次onMount函数。它产生了许多问题,因为我的onMount函数包含对API的调用。这意味着打给Api的电话翻了一番。很长一段时间以来,我都不知道为什么会这样。最近,我注意到布局组件有一个触发转换的包装器。当我移除转换时,onMount被按预期的方式调用了一次。另一方面,我不想失去过渡,因为页面看起来很糟糕。如何解决这个问题?

PageTransitions.svelte:

代码语言:javascript
运行
AI代码解释
复制
<script>
  import { fly } from "svelte/transition";
  export let refresh = "";
</script>

{#key refresh}
  <div in:fly={{ y: -50, duration: 250, delay: 300 }} out:fly={{ y: -50, duration: 250 }} class="flex flex-1">
    <slot>Zawartość</slot>
  </div>
{/key}

layout.svelte:

代码语言:javascript
运行
AI代码解释
复制
<script>
  import { googleMap } from "./../stores.js";
  import { page } from "$app/stores";
  import Footer from "$lib/Footer.svelte";
  import Header from "$lib/Header.svelte";
  import PageTransitions from "$lib/PageTransitions.svelte";
  import Notifications from "svelte-notifications";
  import "../app.css";
  import { GOOGLE_API_KEY } from "$lib/constants.js";
  import { setContext } from "svelte";
  import { writable } from "svelte/store";

  const url = `https://maps.googleapis.com/maps/api/js?key=${GOOGLE_API_KEY}&libraries=places,directions`;

  let isSideMenuOpen = setContext("isSideMenuOpen", writable(false));

  $: loaded = $googleMap.loaded;

  const onLoad = () => {
    $googleMap.loaded = true;
    console.log("Google Maps SDK loaded…", window.google);
  };
</script>

<svelte:head>
  {#if !loaded}
    <script
      src={url}
      type="application/javascript"
      defer
      async
      on:load={onLoad}></script>
  {/if}
</svelte:head>

<Notifications>
  <div
    class="h-screen flex flex-col bg-gray-50 dark:bg-gray-900"
    class:overflow-hidden={isSideMenuOpen}
  >
    <Header />

    <PageTransitions refresh={$page.path}>
      <slot>Strona</slot>
    </PageTransitions>

    <Footer />
  </div>
</Notifications>

modules.svelte (示例组件):

代码语言:javascript
运行
AI代码解释
复制
<script context="module">
  export const ssr = false;
  export const prerender = true;

  export async function load({ session }) {

    if (!session.authenticated) {
      return {
        status: 302,
        redirect: "/auth/login",
      };
    }
    return {
      props: {
        authenticated: session.authenticated,
        token: session.token,
        user: session.user,
      },
    };
  }
</script>

<script>
    import { slide } from 'svelte/transition';
  import GenericTable from "$lib/GenericTable.svelte";
  import { profile, modules } from "../../stores";
  import { getModuleDataURL, getModuleTypeDataURL, get, del } from "$lib/api";
  import GenericRow from "$lib/Rows/ModuleRow.svelte";
  import { onMount } from "svelte";
  import Loader from "$lib/Loader.svelte";
  import { getNotificationsContext } from "svelte-notifications";

  const { addNotification } = getNotificationsContext();

  let loading = false;

  export let authenticated;
  export let token;
  export let user;

  const siteHeader = "Moduły";
  const rootPath = "modules";

  let filters = {
    moduleType: null,
    imei: "",
    serialNumber: "",
    phoneNumber: "",
    isActive: null,
    desc: "",
    id: null,
  };

  const filtersChange = () => {
    let filteredItems = [...$modules.items];

    $modules.filters = false;
    if (
      filters.moduleType ||
      filters.id ||
      filters.desc.length > 2 ||
      filters.isActive !== null ||
      filters.imei.length > 2 ||
      filters.serialNumber.length > 2 ||
      filters.phoneNumber.length > 2
    ) {
      $modules.filters = true;
    }

    if (filters.moduleType) {
      filteredItems = filteredItems.filter(
        (item) => item.moduleType.id === filters.moduleType.value
      );
    }
    if (filters.isActive !== null) {
      filteredItems = filteredItems.filter(
        (item) => item.isActive === filters.isActive
      );
    }
    if (filters.imei.length > 2) {
      filteredItems = filteredItems.filter((item) =>
        item.imei.includes(filters.imei)
      );
    }
    if (filters.serialNumber.length > 2) {
      filteredItems = filteredItems.filter((item) =>
        item.serialNumber.includes(filters.serialNumber)
      );
    }
    if (filters.phoneNumber.length > 2) {
      filteredItems = filteredItems.filter((item) =>
        item.phoneNumber.includes(filters.phoneNumber)
      );
    }
    if (filters.desc.length > 2) {
      filteredItems = filteredItems.filter((item) =>
        item.desc ? item.desc.includes(filters.desc) : false
      );
    }
    if (filters.id === "DESC") {
      filteredItems.sort((a, b) => (a.id > b.id ? 1 : -1));
    } else if (filters.id === "ASC") {
      filteredItems.sort((a, b) => (a.id < b.id ? 1 : -1));
    }
    $modules.filteredModules = filteredItems;
  };

  const urlModuleType = getModuleTypeDataURL();
  const urlModuleData = getModuleDataURL();

  const deleteItem = async (id) => {
    loading = true;
    const url = getModuleDataURL() + "?id=" + id;
    try {
      const result = await del(url, token, false);
      if (result.status) {
        $modules.items = $modules.items.filter((item) => id !== item.id);
        $modules.filteredModules = $modules.filteredModules.filter(
          (item) => id !== item.id
        );
        addNotification({
          text: "Usunięto moduł o id - " + id,
          position: "bottom-right",
          type: "success",
          removeAfter: 4000,
        });
      } else throw result.message;
    } catch (err) {
      console.error(err);
      addNotification({
        text: err,
        position: "bottom-right",
        type: "danger",
        removeAfter: 4000,
      });
    }
    loading = false;
  };

  onMount(async () => {
    loading = true;
    $modules.filters = false;
    $modules.filteredGroups = [];
    try {
      const resultModules = await get(
        urlModuleData + "?$orderby=isActive desc,id",
        token
      );
      if (resultModules.data) $modules.items = resultModules.data.items;

      const resultModuleTypes = await get(urlModuleType, token);
      if (resultModuleTypes.data)
        $modules.moduleTypes = resultModuleTypes.data.items;
    } catch (err) {
      console.error(err);
      addNotification({
        text: "Podczas komunikacji z serwerem wystąpił błąd. Spróbuj raz jeszcze. Jeśli problem się powtórzy, skontaktuj się z administratorem aplikacji.",
        position: "bottom-right",
        type: "danger",
        removeAfter: 4000,
      });
    }
    loading = false;
  });

  let virtualListData = [];
  $: virtualListData = $modules.filters
    ? $modules.filteredModules
    : $modules.items;

  let moduleTypes = [];
  $: moduleTypes = $modules.moduleTypes.map((item) => ({
    value: item.id,
    label: item.type,
  }));

  const widths = ["5%", "15%", "10%", "10%", "15%", "15%", "20%", "10%"];

  let listTableHead = [];
  $: listTableHead = [
    {
      id: 1,
      name: "ID",
      filter: true,
      type: "id",
    },
    {
      id: 2,
      name: "IMEI",
      filter: true,
      label: "imei",
      type: "text",
      placeholder: "Wpisz minimum 3 znaki",
      onInput: filtersChange,
    },
    {
      id: 3,
      name: "Typ modułu",
      filter: true,
      label: "moduleTypes",
      type: "select",
      placeholder: "-",
      items: moduleTypes,
      select: (e) => {
        filters.moduleType = e.detail;
        filtersChange();
      },
      clear: () => {
        filters.moduleType = null;
        filtersChange();
      },
    },
    {
      id: 4,
      name: "Aktywność",
      filter: true,
      label: "isActive",
      type: "select",
      placeholder: "-",
      items: [
        { value: true, label: "Aktywny" },
        { value: false, label: "Nieaktywny" },
      ],
      select: (e) => {
        filters.isActive = e.detail.value;
        filtersChange();
      },
      clear: () => {
        filters.isActive = null;
        filtersChange();
      },
    },
    {
      id: 5,
      name: "Numer telefonu",
      filter: true,
      label: "phoneNumber",
      type: "text",
      placeholder: "Wpisz minimum 3 znaki",
      onInput: filtersChange,
    },
    {
      id: 6,
      name: "Numer seryjny",
      filter: true,
      label: "serialNumber",
      type: "text",
      placeholder: "Wpisz minimum 3 znaki",
      onInput: filtersChange,
    },
    {
      id: 7,
      name: "Opis",
      filter: true,
      label: "desc",
      type: "text",
      placeholder: "Wpisz minimum 3 znaki",
      onInput: filtersChange,
    },
    {
      id: 8,
      name: "Dodaj nowy moduł",
      type: "addNew",
    },
  ];
</script>

<main class="w-full flex flex-1 overflow-y-auto bg-red-100">
  <div class="p-2 overflow-y-auto flex flex-1">
    {#if loading}
      <Loader />
    {/if}
    <div
      transition:slide
      style="display:{loading ? 'none' : 'block'}"
      class="flex flex-col flex-1 items-center justify-center"
    >
      <GenericTable
        {siteHeader}
        {filtersChange}
        {deleteItem}
        {virtualListData}
        {widths}
        {listTableHead}
        {filters}
        {rootPath}
        {GenericRow}
      />
    </div>
  </div>
</main>

我试过的是:

  1. 我试图从PageTransitions组件中删除layout.svelte,它在onMount函数方面有帮助,但是页面看起来很糟糕。
  2. 我尝试将转换分别移动到每个组件,部分工作,但不是所有地方。
  3. 尝试将onMount函数内容移动到Load函数,但我无法编译

这一切为什么要发生?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-02 08:01:01

有一个相关的问题有文档化的这里 (没有解决方案)。

根本原因是时间问题。layout.sveltePageTransitions.svelte中更改<slot/>。这会导致新的插槽/页面加载甚至触发onMount。

新的页面也会在屏幕上显示几毫秒,因为还没有发生转换!

更改插槽后,Svelte将触发一个$page存储更新。在您的代码中,这将导致转换为update ({#key refresh}),从而再次加载<slot/>

如果不修改Svelte本身,就无法更改<slot/> exchange和$page存储集之间的时间安排。

此代码触发转换,并且只导致一个组件挂载。

layout.svelte:

代码语言:javascript
运行
AI代码解释
复制
<script context="module">
    export const load = async ({ url }) => ({ props: { refresh: url } });
</script>
<script>
    import { googleMap } from "./../stores.js";
    import Footer from "$lib/Footer.svelte";
    import Header from "$lib/Header.svelte";
    import PageTransitions from "$lib/PageTransitions.svelte";
    import Notifications from "svelte-notifications";
    import "../app.css";
    import { GOOGLE_API_KEY } from "$lib/constants.js";
    import { setContext } from "svelte";
    import { writable } from "svelte/store";

    export let refresh;
    const url = `https://maps.googleapis.com/maps/api/js?key=${GOOGLE_API_KEY}&libraries=places,directions`;

    let isSideMenuOpen = setContext("isSideMenuOpen", writable(false));

    $: loaded = $googleMap.loaded;

    const onLoad = () => {
      $googleMap.loaded = true;
      console.log("Google Maps SDK loaded…", window.google);
    };
  </script>

  <svelte:head>
    {#if !loaded}
      <script
        src={url}
        type="application/javascript"
        defer
        async
        on:load={onLoad}></script>
    {/if}
  </svelte:head>

  <Notifications>
    <div
      class="h-screen flex flex-col bg-gray-50 dark:bg-gray-900"
      class:overflow-hidden={isSideMenuOpen}
    >
      <Header />

      <PageTransitions {refresh}>
        <slot>Strona</slot>
      </PageTransitions>

      <Footer />
    </div>
  </Notifications>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71702763

复制
相关文章
代理技术 | 重磅,代理服务器背后的故事(正向、反向代理)
传说中的代理服务技术是一门很古老的技术,互联网早期就已经出现,一般来说,实现实现代理技术的实现就是在服务器上安装代理软件,成为代理服务器,从而配置\实现代理技术。 其实网络代理的玩法真的很多。之前知道如何使用,今天我们看看代理背后的故事。 我们以nginx为例,常用的代理技术有:正向代理、反向代理和透明代理。真正项目中常用的是反向代理和正向代理,透明代理我们了解一下就可以,本文重点讲正向代理和反向代理。 老规矩,走一波概念: 1
码神联盟
2018/04/02
2K0
代理技术 | 重磅,代理服务器背后的故事(正向、反向代理)
使用Cloudflare代理无443/80端口权限的服务器
使用Cloudflare代理无443/80端口权限的服务器 然后配置回源端口, 以8443为例
纯情
2023/04/27
13.6K1
使用Cloudflare代理无443/80端口权限的服务器
Ubuntu部署squid代理服务器
squid是一款高性能的代理缓存服务器,常用来部署HTTP(S)代理服务器。本文是在Ubuntu上使用squid部署HTTP(S)代理服务器的方法总结。
drunkdream
2020/01/02
3.7K0
Squid缓存代理服务器安装部署
1、代理的工作机制 作为应用层的代理服务软件,Squid主要提供缓存加速和应用层过滤控制的功能。当客户机通过代理来请求Web页面时,指定的代理服务器会先检查自己的缓存,如果缓存中已经有客户机需要访问的页面,则直接将缓存中的页面内容反馈给客户机;如果缓存中没有客户机需要访问的页面,则由代理服务器向Internet发送访问请求,当获得返回的Web页面以后,将网页数据保存到缓存中并发送给客户机。 HTTP代理的缓存加速对象主要是文字、图像等静态Web元素。使用缓存机制后,当客户机在不同的时候访问同一Web元素,或者不同的客户机访问相同的Web元素时,可以直接从代理服务器的缓存中获得结果。这样就大大减少了向Internet重复提交Web请求的过程,提高了客户机的Web访问响应速度。 由于客户机的Web访问请求实际上是由代理服务器来代替完成的,从而可以隐藏用户的真实IP地址,起到一定的保护作用。另一方面,代理服务器担任着类似“经纪人”的角色,所以有机会针对要访问的目标、客户机的地址、访问的时间端进行过滤控制。
星哥玩云
2022/07/26
1.4K0
Squid缓存代理服务器安装部署
容器部署和无服务器计算那些事儿
对于网站代码托管,目前有两种方式,一种是 docker 容器部署,一种是无服务器计算部署。
程序那些事儿
2023/03/07
3.4K0
容器部署和无服务器计算那些事儿
无服务器和 Kubernetes 原生 Java 部署实践
作者 | Daniel Oh 译者 | 平川 策划 | 丁晓昀 随着云部署的兴起,IT 部门使用的物理服务器减少,用电量也相应降低,结果是通过减少碳排放帮助缓解了气候变化。云架构有助于实现这一点,因为它们不需要维护竖井式的计算资源,而是在需要保持业务服务运行时,高效共享所在云上的可用资源。 然而短期内,云迁移的这些好处对于二氧化碳的排放并没有产生显著的影响。这是因为采用云的速度比转向无碳基础设施的速度要快得多。例如,谷歌云目前已实现碳中和,但他们正在努力成为无碳、可持续的云计算系统。 与此同时,开
深度学习与Python
2023/03/29
9350
无服务器和 Kubernetes 原生 Java 部署实践
无服务器实现openai接口反向代理和额度查询
使用Cloudflare代理openai接口,并实现简单查询额度。 实现接口代理 将代码部署到Cloudflare的worker平台(其他支持worker的平台也可) 替换自己代码中的api.openai.com为你自己的worker域名,例如 your.worker.domain 查询使用情况 访问地址 https://your.worker.domain}/usage/{sk-key} 即可 Worker 代码 // code from https://www.rehiy.com/post/500 a
若海
2023/05/03
3.2K0
关于部署war包到服务器存在代理的问题
将java工程打成war部署到linux服务器后,在服务器上存在代理的情况下,我们java工程如果存在接口对外有发送http请求时,我们的java代码可能也要相应的有设置对应于服务器上的代理的代码.具体如下
全栈程序员站长
2022/06/30
6780
关于部署war包到服务器存在代理的问题
nodejs 代理服务器_nodejs部署前端项目
将 a.html 请求地址改为 /api/b,那么发送请求的时候会自动补上主机和端口号http://localhost:3000
全栈程序员站长
2022/11/17
1.3K0
nodejs 代理服务器_nodejs部署前端项目
管理混合云和多云:代理或无代理?
导语 混合云在节省更多IT成本方面提供更多的潜力,并将这些成本节约转向改善业务成果,但却带来了一些独特的挑战。人工手动的流程在一个混合的世界变得难以管理,因为云实例会有一些变化,毕竟云端中没有工作人员
静一
2018/03/28
1K0
管理混合云和多云:代理或无代理?
java动态代理--代理接口无实现类
转载自 http://blog.csdn.net/zhu_tianwei/article/details/40076391
allsmallpig
2021/02/25
7200
无服务器部署php程序,以typecho为例
引入:本教程适合无服务器搭建php服务的兄弟们 注:1.使用此教程的方法最好加上CDN加速,否则访问速度可以逼死你 环境配置:  初中英语  能畅通访问github的网络环境  懂得提问的智慧  愿意折腾的双手 一.注册Github及Vercel账号,配置git环境 1.电脑环境配置请参考Git工具配置 2.账户配置 1.1.Github配置 首先你需要一个Github账户 新建一个仓库 推荐私人仓 在菜单里搜索Git Bash,设置user.name和user.email配置信息:PLAINTEXT1 2
Tianli
2023/03/03
2K0
使用 Docker 部署 Jenkins 代理(主从)控制服务器
自动化是 DevOps 的核心。各种自动化工具和技术真正实现了持续集成和持续交付的概念。这些工具多年来发展迅速,但似乎永远存在的一个名字是Jenkins。
用户4235284
2023/10/14
6570
使用 Docker 部署 Jenkins 代理(主从)控制服务器
Nginx代理服务器环境快速搭建部署
步骤 01.nginx 配置文件准备执行如下命令写入到/app/nginx/conf/nginx.conf文件中
全栈工程师修炼指南
2022/09/29
8440
Nginx代理服务器环境快速搭建部署
无厨房的餐厅,无服务器的计算
这个时候,你可能需要了解下"无服务器"的魅力了。服务器带来无穷无尽的困扰是目前"无服务器"架构受欢迎的重要原因之一,你的老板不可能总容忍你拿服务器故障来当影响业务运行的借口,"无服务器"则让人们摆脱了这种困扰。
科技云报道
2022/04/15
3.2K0
无厨房的餐厅,无服务器的计算
快速部署隧道代理:四步教你搭建个人代理服务器
嗨,大家好!作为一名互联网技术爱好者,我今天想和大家分享一个有趣的话题:如何快速部署隧道代理,搭建起自己的个人代理服务器!没错,你没听错,你可以拥有一个属于自己的代理服务器,让你在互联网世界中畅行无阻!接下来,我将为你详细介绍这个过程,让你可以轻松搭建起个人的代理服务器。
用户614136809
2023/09/18
1.8K0
浏览器代理服务器没有响应解决方案怎么办_电脑代理服务器无响应
前几天,为了满足爬虫的需要,我在自己电脑上设置了一个代理IP。在利用代理IP运行爬虫程序一天之后,终于爬够了所需的数据量。但是非常奇怪的是,爬完虫的第二天,我用浏览器就打不开网页了,浏览器一直提示我代理服务器没有响应,或者说是ERR_PROXY_CONNECTION_FAILED这一错误。我刚开始的时候以为是浏览器的问题,但是在更换了许多浏览器之后依然没有用。
全栈程序员站长
2022/11/17
2.8K0
浏览器代理服务器没有响应解决方案怎么办_电脑代理服务器无响应
【无服务器架构】跨平台的无服务器计算Knative 简介
Knative(发音为kay-nay-tiv)扩展了Kubernetes,以提供一组中间件组件,这些组件对于构建可在任何地方运行的现代,以源代码为中心和基于容器的应用程序必不可少:本地,云端或什至是第三方数据中心。
架构师研究会
2019/12/27
4.5K0
【无服务器架构】跨平台的无服务器计算Knative 简介
使用 vercel 无服务器部署 NeteaseCloudMusicApi-网易云音乐API
Vercel 之前叫Zeit,是一家提供静态网站托管的云平台,支持从 Github, GitLab, Bitbucket 等代码仓库中自动拉取代码 然后进行项目打包和部署等功能。
小狐狸说事
2022/11/17
2.6K1
使用 vercel 无服务器部署 NeteaseCloudMusicApi-网易云音乐API
点击加载更多

相似问题

代理背后的无服务器插件

10

Api-nginx代理背后的平台坞部署

19

Apache背后的代理react服务器

34

Jetty反向代理背后的Keycloak服务器

11

Traefik代理背后的Java Grpc服务器

199
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档