重构项目架构

前言
我们上篇文章对整个项目进行一个整体的规划,其中对于APP类规划了类,本篇文章我们就来实现这个规划;

class App {
  //加载页面
  constructor() {}

  //获取位置
  _getPosition() {}

  //接受位置
  _loadMap() {}

  //在地图上点击展现表单
  _showForm() {}

  //切换表单的输入选项
  _toggleElevationField() {}

  //提交表单之后生成新的运动
  _newWorkout() {}
}

● 这个就是初步的架构代码,现在我们只需要把功能代码放进去即可

class App {
  //加载页面
  constructor() {}

  //获取位置
  _getPosition() {
    if (navigator.geolocation)
      navigator.geolocation.getCurrentPosition(this._loadMap, function () {
        alert('无法获取你的位置!');
      });
  }

  //接受位置
  _loadMap(position) {
    const { latitude } = position.coords;
    const { longitude } = position.coords;
    const coords = [latitude, longitude];
    map = L.map('map').setView(coords, 13);

    L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    }).addTo(map);

    map.on('click', function (mapE) {
      mapEvent = mapE;
      form.classList.remove('hidden');
      inputDistance.focus();
    });
  }

  //在地图上点击展现表单
  _showForm() {}

  //切换表单的输入选项
  _toggleElevationField() {}

  //提交表单之后生成新的运动
  _newWorkout() {}
}

● 现在我们来将计划实例化出来,并在构造函数中渲染

const app = new App();

● 目前我们再创建App类之后无法立即获取用户的问题,所以我们需要在构造函数中调用_getPosition方法来立即获取用户的地理位置。这是一个常见的设计模式,通常用来确保在应用加载后尽快执行某些初始化操作。

  //加载页面
  constructor() {
    this._getPosition();
  }

● 这样不出意外的话,我们的功能应该能正常的运行
在这里插入图片描述

● 所以现在在类中将map和mapEvent进行宣告,但是像地图及地图事件肯定是一次性的,后面不不需要对其进行修改,所以当成私有字段;

class App {
  #map;
  #mapEvent;
  //加载页面
  constructor() {
    this._getPosition();
  }
  。。。。。。
}

● 之后,我们在调用map的时候记住改一下私有字段的宣告方式即可;

 //接受位置
  _loadMap(position) {
    const { latitude } = position.coords;
    const { longitude } = position.coords;
    const coords = [latitude, longitude];
    this.#map = L.map('map').setView(coords, 13);

    L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    }).addTo(this.#map);

    this.#map.on('click', function (mapE) {
      this.#mapEvent = mapE;
      form.classList.remove('hidden');
      inputDistance.focus();
    });
  }

● 下一步我们将生成运动表单的函数进行重构,我们直接将我们展现标记的函数放入我们之前做规划的函数体当中,也就是_newWorkout
//提交表单之后生成新的运动

  _newWorkout(e) {
    e.preventDefault(); //组织表单默认行为

    //将表格输入内容置空
    inputDistance.value =
      inputDuration.value =
      inputCadence.value =
      inputElevation.value =
        '';

    //展现标记
    const { lat, lng } = mapEvent.latlng;
    L.marker([lat, lng])
      .addTo(map)
      .bindPopup(
        L.popup({
          maxWidth: 250,
          minWidth: 100,
          autoClose: false,
          closeOnClick: false,
          className: 'running-popup',
        })
      )
      .setPopupContent('跑步')
      .openPopup();
  }
}

● 然后还是在构造函数中宣告

constructor() {
    this._getPosition();
    form.addEventListener('submit', this._newWorkout);

    inputType.addEventListener('change', function () {
      //改变的时候判断是否存在隐藏类,有就去除,没有就添加
      inputElevation
        .closest('.form__row')
        .classList.toggle('form__row--hidden');
      inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
    });
  }

● 但是,注意事件监听器中的 this 关键字通常指向触发事件的元素,也就是事件绑定的元素本身。所以在调用新建运动项目时候,我们需要手动绑定一下this

//加载页面
  constructor() {
    this._getPosition();
    form.addEventListener('submit', this._newWorkout.bind(this));

    inputType.addEventListener('change', function () {
      //改变的时候判断是否存在隐藏类,有就去除,没有就添加
      inputElevation
        .closest('.form__row')
        .classList.toggle('form__row--hidden');
      inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
    });
  }

● 接着我们对在地图上面展示表单进行一个重构,注意监听事件和绑定事件一样,记着调用时候手动绑定一下

  //接受位置
  _loadMap(position) {
    const { latitude } = position.coords;
    const { longitude } = position.coords;
    const coords = [latitude, longitude];
    console.log(this);
    this.#map = L.map('map').setView(coords, 13);

    L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    }).addTo(this.#map);

    this.#map.on('click', this._showForm.bind(this));
  }

  //在地图上点击展现表单
  _showForm(mapE) {
    this.#mapEvent = mapE;
    form.classList.remove('hidden');
    inputDistance.focus();
  }

在这里插入图片描述

● 接下来我们来处理关于隐藏类的函数

  //加载页面
  constructor() {
    this._getPosition();
    form.addEventListener('submit', this._newWorkout.bind(this));
    inputType.addEventListener('change', this._toggleElevationField);
  }
。。。。。。
 //切换表单的输入选项
  _toggleElevationField() {
    //改变的时候判断是否存在隐藏类,有就去除,没有就添加
    inputElevation.closest('.form__row').classList.toggle('form__row--hidden');
    inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
  }

在这里插入图片描述

之后我们基本的架构也就调整完了,看看是不是整洁了很多

'use strict';

// prettier-ignore
const months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

const form = document.querySelector('.form');
const containerWorkouts = document.querySelector('.workouts');
const inputType = document.querySelector('.form__input--type');
const inputDistance = document.querySelector('.form__input--distance');
const inputDuration = document.querySelector('.form__input--duration');
const inputCadence = document.querySelector('.form__input--cadence');
const inputElevation = document.querySelector('.form__input--elevation');
class App {
  #map;
  #mapEvent;
  //加载页面
  constructor() {
    this._getPosition();
    form.addEventListener('submit', this._newWorkout.bind(this));
    inputType.addEventListener('change', this._toggleElevationField);
  }

  //获取位置
  _getPosition() {
    if (navigator.geolocation)
      navigator.geolocation.getCurrentPosition(
        this._loadMap.bind(this),
        function () {
          alert('无法获取你的位置!');
        }
      );
  }

  //接受位置
  _loadMap(position) {
    const { latitude } = position.coords;
    const { longitude } = position.coords;
    const coords = [latitude, longitude];
    this.#map = L.map('map').setView(coords, 13);

    L.tileLayer('https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', {
      attribution:
        '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    }).addTo(this.#map);

    this.#map.on('click', this._showForm.bind(this));
  }

  //在地图上点击展现表单
  _showForm(mapE) {
    this.#mapEvent = mapE;
    form.classList.remove('hidden');
    inputDistance.focus();
  }

  //切换表单的输入选项
  _toggleElevationField() {
    //改变的时候判断是否存在隐藏类,有就去除,没有就添加
    inputElevation.closest('.form__row').classList.toggle('form__row--hidden');
    inputCadence.closest('.form__row').classList.toggle('form__row--hidden');
  }

  //提交表单之后生成新的运动
  _newWorkout(e) {
    e.preventDefault(); //组织表单默认行为

    //将表格输入内容置空
    inputDistance.value =
      inputDuration.value =
      inputCadence.value =
      inputElevation.value =
        '';

    //展现标记
    const { lat, lng } = this.#mapEvent.latlng;
    L.marker([lat, lng])
      .addTo(this.#map)
      .bindPopup(
        L.popup({
          maxWidth: 250,
          minWidth: 100,
          autoClose: false,
          closeOnClick: false,
          className: 'running-popup',
        })
      )
      .setPopupContent('跑步')
      .openPopup();
  }
}

const app = new App();

注意:现在OpenStreetMap国内访问不了,如果想要访问的话,需要用特殊的上网方法,不过这里不显示地图瓦片也没事,我们主要去注意一下我们的功能;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/924188.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

哈希C++

文章目录 一.哈希的概念1.直接定址法2.负载因子 二.哈希函数1.除法散列法 / 除留余数法2.乘法散列法3.全域散列法&#xff08;了解&#xff09; 三.处理哈希冲突哈希冲突&#xff1a;1.开放定址法&#xff08;1&#xff09;线性探测&#xff1a;&#xff08;2&#xff09;二次探…

转录组数据挖掘(生物技能树)(第11节)下游分析

转录组数据挖掘&#xff08;生物技能树&#xff09;&#xff08;第11节&#xff09; 文章目录 R语言复习转录组数据差异分析差异分析的输入数据操作过程示例一&#xff1a;示例二&#xff1a;示例三&#xff1a;此代码只适用于人的样本 R语言复习 #### 读取 ####dat read.deli…

Diving into the STM32 HAL-----Cyclic Redundancy Check笔记

在数字系统中&#xff0c;数据完全有可能被损坏&#xff0c;特别是当它流经通信介质时。在数字电子学中&#xff0c;消息是等于 0 或 1 的比特流&#xff0c;当这些比特中的一个或多个在传输过程中意外更改时&#xff0c;它就会损坏。因此&#xff0c;消息中始终有一些额外的数…

Swift——类与结构体

一.结构体 在swift的标准库中&#xff0c;大部分的类型都是结构体&#xff0c;比如&#xff1a;Int&#xff0c;Double&#xff0c;String&#xff0c;Array&#xff0c;Dictionary等等&#xff0c;它们都是结构体。 结构体定义如下&#xff1a; struct Person {var name:St…

反射泛型

反射 class 包含哪些内容&#xff1f; 当使用new 对象时需要构造函数是public 的&#xff0c;而当变成私有时再new则会报错 反射通过私有构造方法创建对象&#xff0c;破环单例模式 Clazz.getDeclared(构造函数&#xff0c;方法属性等)和直接get构造函数&#xff0c;方法属性等…

RHCE——SELinux

SELinux 什么是SELinux呢&#xff1f;其实它是【Security-Enhanced Linux】的英文缩写&#xff0c;字母上的意思就是安全强化Linux的意思。 SELinux是由美国国家安全局(NSA)开发的&#xff0c;当初开发的原因是很多企业发现&#xff0c;系统出现问题的原因大部分都在于【内部…

etcd、kube-apiserver、kube-controller-manager和kube-scheduler有什么区别

在我们部署K8S集群的时候 初始化master节点之后&#xff08;在master上面执行这条初始化命令&#xff09; kubeadm init --apiserver-advertise-address10.0.1.176 --image-repository registry.aliyuncs.com/google_containers --kubernetes-version v1.16.0 --service…

uniapp定义new plus.nativeObj.View实现APP端全局弹窗

为什么要用new plus.nativeObj.View在APP端实现弹窗&#xff1f;因为uni.showModal在APP端太难看了。 AppPopupView弹窗函数参数定义 参数一:弹窗信息(所有属性可不填&#xff0c;会有默认值) 1.title:"", //标题 2.content:"", //内容 3.confirmBoxCo…

一文学习开源框架OkHttp

OkHttp 是一个开源项目。它由 Square 开发并维护&#xff0c;是一个现代化、功能强大的网络请求库&#xff0c;主要用于与 RESTful API 交互或执行网络通信操作。它是 Android 和 Java 开发中非常流行的 HTTP 客户端&#xff0c;具有高效、可靠、可扩展的特点。 核心特点 高效…

DRM(数字权限管理技术)防截屏录屏----视频转hls流加密、web解密播放

提示&#xff1a;视频转hls流加密、web解密播放 需求&#xff1a;研究视频截屏时&#xff0c;播放器变黑&#xff0c;所以先研究的视频转hls流加密 文章目录 [TOC](文章目录) 前言一、工具ffmpeg、openssl二、后端nodeexpress三、web播放四、文档总结 前言 ‌HLS流媒体协议‌&a…

Rk3588 onnx转rknn,出现 No module named ‘rknn‘

一、操作步骤&#xff1a; rk3588 需要将yolo11 的模型onnx转rknn。 https://github.com/airockchip/rknn_model_zoo/tree/main/examples/yolo11 这个是用yolo11训练的模型&#xff0c;有80种类型。 完整下载下来后&#xff0c;在按文档描述下载模型下来&#xff1a; 然后进…

IDEA 解决Python项目import导入报错、引用不到的问题

使用Idea 23.1 专业版编写Python项目时&#xff0c;import 导入爆红&#xff0c;无法引入其他package的代码&#xff0c;现象如&#xff1a; 解决方案&#xff1a;Idea表头打开 File -> Project Settring 解决效果&#xff1a;

unity 使用UI上的数字按钮,给text添加数字,并且显示光标,删除光标前数字,

今天有个需求&#xff0c;输入身份证&#xff0c;但是不用键盘&#xff0c;要点击按钮输入数字&#xff0c;并且可以控制光标&#xff0c; 1、数字按钮&#xff1a;点击后text添加数字内容 2、删除按钮&#xff1a;删除光标前的一个字符 3、左箭头&#xff1a;移动光标向左移动…

火山引擎VeDI在AI+BI领域的演进与实践

随着数字化时代的到来&#xff0c;企业对于数据分析与智能决策的需求日益增强。作为新一代企业级数据智能平台&#xff0c;火山引擎数智平台VeDI基于字节跳动多年的“数据驱动”实践经验&#xff0c;也正逐步在AI&#xff08;人工智能&#xff09;与BI&#xff08;商业智能&…

【逐行注释】自适应观测协方差R的AUKF(自适应无迹卡尔曼滤波,MATLAB语言编写),附下载链接

文章目录 自适应R的UKF逐行注释的说明运行结果部分代码各模块解释 自适应R的UKF 自适应无迹卡尔曼滤波&#xff08;Adaptive Unscented Kalman Filter&#xff0c;AUKF&#xff09;是一种用于状态估计的滤波算法。它是基于无迹卡尔曼滤波&#xff08;Unscented Kalman Filter&…

LLM应用-prompt提示:RAG query重写、相似query生成 加强检索准确率

参考&#xff1a; https://zhuanlan.zhihu.com/p/719510286 1、query重写 你是一名AI助手&#xff0c;负责在RAG&#xff08;知识库&#xff09;系统中通过重构用户查询来提高检索效果。根据原始查询&#xff0c;将其重写得更具体、详细&#xff0c;以便更有可能检索到相关信…

Spring Boot 与 Spring Cloud Alibaba 版本兼容对照

版本选择要点 Spring Boot 3.x 与 Spring Cloud Alibaba 2022.0.x Spring Boot 3.x 基于 Jakarta EE&#xff0c;javax.* 更换为 jakarta.*。 需要使用 Spring Cloud 2022.0.x 和 Spring Cloud Alibaba 2022.0.x。 Alibaba 2022.0.x 对 Spring Boot 3.x 的支持在其发行说明中…

如何通过PHP爬虫模拟表单提交,抓取隐藏数据

引言 在网络爬虫技术中&#xff0c;模拟表单提交是一项常见的任务&#xff0c;特别是对于需要动态请求才能获取的隐藏数据。在电商双十一、双十二等促销活动期间&#xff0c;商品信息的实时获取尤为重要&#xff0c;特别是针对不断变化的价格和库存动态。为了满足这种需求&…

嵌入式Qt使用ffmpeg视频开发记录

在此记录一下Qt下视频应用开发的自学历程&#xff0c;可供初学者参考和避雷。 了解常用音频格式yuv420p、h264等了解QML&#xff0c;了解QVideoOutput类的使用&#xff0c;实现播放yuv420p流参考ffmpeg官方例程&#xff0c;调用解码器实现h264解码播放 不需要手动分帧。ffmpeg…

Java设计模式笔记(一)

Java设计模式笔记&#xff08;一&#xff09; &#xff08;23种设计模式由于篇幅较大分为两篇展示&#xff09; 一、设计模式介绍 1、设计模式的目的 让程序具有更好的&#xff1a; 代码重用性可读性可扩展性可靠性高内聚&#xff0c;低耦合 2、设计模式的七大原则 单一职…