重构项目架构

前言

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

javascript 复制代码
class App {
  //加载页面
  constructor() {}

  //获取位置
  _getPosition() {}

  //接受位置
  _loadMap() {}

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

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

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

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

javascript 复制代码
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() {}
}

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

javascript 复制代码
const app = new App();

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

javascript 复制代码
  //加载页面
  constructor() {
    this._getPosition();
  }

● 这样不出意外的话,我们的功能应该能正常的运行

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

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

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

javascript 复制代码
 //接受位置
  _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

//提交表单之后生成新的运动

javascript 复制代码
  _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();
  }
}

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

javascript 复制代码
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

javascript 复制代码
//加载页面
  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');
    });
  }

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

javascript 复制代码
  //接受位置
  _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();
  }

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

javascript 复制代码
  //加载页面
  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');
  }

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

javascript 复制代码
'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国内访问不了,如果想要访问的话,需要用特殊的上网方法,不过这里不显示地图瓦片也没事,我们主要去注意一下我们的功能;

相关推荐
yuyuxun12 小时前
协同过滤的校园二手物品智能推荐系统的设计与实现 毕业设计-附源码40082
javascript·vue.js·spring boot·python·数据分析·django·课程设计
上海潭龙东海科技有限公司3 小时前
客运站管控之动态孪生技术方案(新增一屏管控模块
数据仓库·人工智能·算法·重构·动态规划
总要学点什么5 小时前
第105篇:三维特效-流动图片墙体效果——让箭头沿墙长滚,它俩竟是同一份代码
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
Agent世界6 小时前
用 CDP 做发布自动化:四道机器闸门与产物验收
前端·javascript
总要学点什么7 小时前
第104篇:三维特效-流动墙体效果——让贴图沿墙流动,它却只肯走一条对角线
开发语言·javascript·ecmascript·gis·webgl·材质·cesium
程序员大阳7 小时前
副队长ES6+教程(3)--解构赋值
前端·javascript·es6·赋值·解构
神膘护体小月半7 小时前
css - 元素背景图由 hover 触发,初次加载时闪动的解决办法
前端·javascript·css
程序员大阳7 小时前
副队长ES6+教程(2)--let 与 const
前端·javascript·es6·const·let·var
曦樂~9 小时前
【Web Development】03JavaScript 基础和事件
开发语言·前端·javascript
码云社区9 小时前
智慧物业系统选型指南:房屋档案、账单管理与报修协作
前端·javascript·vue.js·智慧物业