JavaScript 编码原则学习笔记(一) | 豆包MarsCode AI刷题

43 阅读2分钟

原则1:各司其职

在Web开发中,HTML、CSS和JavaScript各自承担不同的职责。为了使代码更易于维护和扩展,我们需要遵循以下原则:

  • HTML 负责描述文档的结构。
  • CSS 负责文档的表现。
  • JavaScript 负责文档的行为。

例子:纯展示类交互

比如说,对于一些简单的展示类交互,我们可以尽量减少JavaScript的使用,通过CSS来实现。在实现一个简单的下拉菜单时,我们可以通过CSS的hover伪类来实现,而不需要JavaScript,从而减少js的使用。



  
    Menu
      
        Item 1
        Item 2
        Item 3
      
    
  



.dropdown {
  display: none;
}

nav ul li:hover .dropdown {
  display: block;
}

这样做的好处是减少了JavaScript的依赖,使得代码更加简洁和易于维护。

原则2:组件封装

组件化是现代前端开发中的一个重要概念。通过将功能模块封装成独立的组件,可以提高代码的可复用性和可维护性。

例子:轮播图

HTML 结构

轮播图的HTML结构可以采用无序列表,每个图片作为一个元素。

<div class="carousel"> 
    <ul> 
        <li><img src="image1.jpg" alt="Image 1"></li> 
        <li><img src="image2.jpg" alt="Image 2"></li> 
        <li><img src="image3.jpg" alt="Image 3"></li> 
</div>

CSS 表现

通过CSS绝对定位将图片定位到同一位置,并设置样式。

.carousel {
  position: relative;
  width: 600px;
  height: 400px;
  overflow: hidden;
}

.carousel ul {
  position: absolute;
  left: 0;
  top: 0;
  list-style: none;
  margin: 0;
  padding: 0;
}

.carousel li {
  position: absolute;
  width: 600px;
  height: 400px;
  opacity: 0;
  transition: opacity 0.5s ease-in-out;
}

.carousel li.active {
  opacity: 1;
}

JavaScript 行为

JavaScript负责实现轮播效果,并通过自定义事件解锁控制流。

class Carousel {
  constructor(element) {
    this.element = element;
    this.images = Array.from(this.element.querySelectorAll('li'));
    this.currentIndex = 0;

    this.init();
  }

  init() {
    this.showImage(this.currentIndex);
    this.startAutoPlay();
    this.addEventListeners();
  }

  showImage(index) {
    this.images.forEach((img, i) => {
      if (i === index) {
        img.classList.add('active');
      } else {
        img.classList.remove('active');
      }
    });
  }

  nextImage() {
    this.currentIndex = (this.currentIndex + 1) % this.images.length;
    this.showImage(this.currentIndex);
  }

  startAutoPlay() {
    this.intervalId = setInterval(() => {
      this.nextImage();
    }, 3000);
  }

  stopAutoPlay() {
    clearInterval(this.intervalId);
  }

  addEventListeners() {
    this.element.addEventListener('mouseover', () => this.stopAutoPlay());
    this.element.addEventListener('mouseout', () => this.startAutoPlay());
  }
}

const carouselElement = document.querySelector('.carousel');
const carousel = new Carousel(carouselElement);

如何重构?

插件化

将控制元素抽象成插件,插件和组件之间通过依赖注入方式建立联系,提高扩展性。

// 插件示例
function AutoPlayPlugin(carousel) {
  this.carousel = carousel;
  this.init();
}

AutoPlayPlugin.prototype.init = function() {
  this.carousel.element.addEventListener('mouseover', () => this.stop());
  this.carousel.element.addEventListener('mouseout', () => this.start());
};

AutoPlayPlugin.prototype.start = function() {
  this.intervalId = setInterval(() => {
    this.carousel.nextImage();
  }, 3000);
};

AutoPlayPlugin.prototype.stop = function() {
  clearInterval(this.intervalId);
};

// 使用插件
const carousel = new Carousel(carouselElement);
carousel.use(new AutoPlayPlugin(carousel));

模板化

将HTML模板化,便于扩展和维护。


  <div class="carousel">
    <ul>
      <% for (let i = 0; i < images.length; i++) { %>
        <li><img src="<%= images[i] %>" alt="Image <%= i + 1 %>"></li>
      <% } %>
    </ul>
  </div>

const template = document.querySelector('#carousel-template').innerHTML;
const compiledTemplate = _.template(template);
const images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
const html = compiledTemplate({ images });

document.body.innerHTML = html;
const carouselElement = document.querySelector('.carousel');
const carousel = new Carousel(carouselElement);

抽象化

将通用的组件模型抽象出来,形成可复用的组件库。

class Component {
  constructor(element) {
    this.element = element;
  }

  init() {
    // 初始化逻辑
  }

  addEventListener(event, callback) {
    this.element.addEventListener(event, callback);
  }
}

class Carousel extends Component {
  constructor(element) {
    super(element);
    this.images = Array.from(this.element.querySelectorAll('li'));
    this.currentIndex = 0;
    this.init();
  }

  init() {
    this.showImage(this.currentIndex);
    this.startAutoPlay();
    this.addEventListeners();
  }

  // 其他方法...
}

const carouselElement = document.querySelector('.carousel');
const carousel = new Carousel(carouselElement);

通过以上方法,更好地组织和管理代码,提高项目的可维护性和扩展性。