用原生js做单页应用

下面我将为大家详细讲解如何用原生JS做单页应用的完整攻略。

什么是单页应用?

单页应用(SPA)是指使用Ajax或Websocket等技术,使得网页只需加载一次,就能实现多个页面的效果。

用原生JS做单页应用的步骤

  1. 定义路由
    要实现单页应用,首先需要定义路由,以此来控制页面的跳转和展示。可以使用window.history.pushState()方法或者location.hash来实现路由。

示例代码:

// 定义路由表
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
  { path: '/contact', component: Contact }
]

// 监听路由变化
window.addEventListener('popstate', routeChanged);

// 路由跳转
function navigateTo(path) {
  history.pushState(null, null, path);
  routeChanged();
}

// 路由变化处理函数
function routeChanged() {
  const path = location.pathname;
  const route = routes.find(route => route.path === path) || {component: NotFound};
  document.querySelector('#content').innerHTML = new route.component().render();
}
  1. 定义组件
    为了实现复用和组合,需要将页面拆分成多个组件。每个组件可以由一个HTML模板和一个JS逻辑文件组成。

示例代码:

// Home组件
class Home {
  constructor() {
    this.template = `
      <h1>Welcome to Home Page</h1>
      <p>Home Page Content Here</p>
    `;
  }

  render() {
    return this.template;
  }
}

// About组件
class About {
  constructor() {
    this.template = `
      <h1>About Us</h1>
      <p>About Us Content Here</p>
    `;
  }

  render() {
    return this.template;
  }
}

// Contact组件
class Contact {
  constructor() {
    this.template = `
      <h1>Contact Us</h1>
      <p>Contact Us Content Here</p>
    `;
  }

  render() {
    return this.template;
  }
}

// NotFound组件
class NotFound {
  constructor() {
    this.template = `
      <h1>Not Found</h1>
      <p>404 Page Not Found</p>
    `;
  }

  render() {
    return this.template;
  }
}
  1. 编写事件处理函数和业务逻辑
    单页应用中,事件处理函数和业务逻辑通常写在组件中。可以使用事件委托和事件监听等方法来实现交互效果。

示例代码:

// 定义事件处理函数
function handleClick(event) {
  event.preventDefault();
  const path = event.target.href;
  navigateTo(path);
}

// 组件中使用事件处理函数
class Navigation {
  constructor() {
    this.template = `
      <nav>
        <ul>
          <li><a href="/" class="link">Home</a></li>
          <li><a href="/about" class="link">About</a></li>
          <li><a href="/contact" class="link">Contact</a></li>
        </ul>
      </nav>
    `;
  }

  render() {
    const element = document.createElement('div');
    element.innerHTML = this.template.trim();
    element.addEventListener('click', handleClick); // 事件委托
    return element;
  }
}

// 业务逻辑处理函数
function handleSubmit(event) {
  event.preventDefault();
  const formData = new FormData(event.target);
  const data = Object.fromEntries(formData.entries());
  // 处理提交数据...
}

// 组件中使用业务逻辑处理函数
class Form {
  constructor() {
    this.template = `
      <form>
        <label>
          Name: <input type="text" name="name" required>
        </label>
        <label>
          Email: <input type="email" name="email" required>
        </label>
        <button type="submit">Submit</button>
      </form>
    `;
  }

  render() {
    const element = document.createElement('div');
    element.innerHTML = this.template.trim();
    element.querySelector('form').addEventListener('submit', handleSubmit);
    return element;
  }
}

示例说明

示例一:基础单页应用

下面是一个基础的单页应用示例,实现了路由跳转和组件渲染。

<html>
<head>
  <title>Example SPA</title>
</head>
<body>
  <nav>
    <ul>
      <li><a href="/" class="link">Home</a></li>
      <li><a href="/about" class="link">About</a></li>
      <li><a href="/contact" class="link">Contact</a></li>
    </ul>
  </nav>
  <div id="content"></div>
  <script>
    // 定义路由表
    const routes = [
      { path: '/', component: Home },
      { path: '/about', component: About },
      { path: '/contact', component: Contact }
    ];

    // 监听路由变化
    window.addEventListener('popstate', routeChanged);

    // 路由跳转
    function navigateTo(path) {
      history.pushState(null, null, path);
      routeChanged();
    }

    // 路由变化处理函数
    function routeChanged() {
      const path = location.pathname;
      const route = routes.find(route => route.path === path) || {component: NotFound};
      document.querySelector('#content').innerHTML = new route.component().render();
    }

    // Home组件
    class Home {
      constructor() {
        this.template = `
          <h1>Welcome to Home Page</h1>
          <p>Home Page Content Here</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // About组件
    class About {
      constructor() {
        this.template = `
          <h1>About Us</h1>
          <p>About Us Content Here</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // Contact组件
    class Contact {
      constructor() {
        this.template = `
          <h1>Contact Us</h1>
          <p>Contact Us Content Here</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // NotFound组件
    class NotFound {
      constructor() {
        this.template = `
          <h1>Not Found</h1>
          <p>404 Page Not Found</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // 定义事件处理函数
    function handleClick(event) {
      event.preventDefault();
      const path = event.target.href;
      navigateTo(path);
    }

    // Navigation组件
    class Navigation {
      constructor() {
        this.template = `
          <nav>
            <ul>
              <li><a href="/" class="link">Home</a></li>
              <li><a href="/about" class="link">About</a></li>
              <li><a href="/contact" class="link">Contact</a></li>
            </ul>
          </nav>
        `;
      }

      render() {
        const element = document.createElement('div');
        element.innerHTML = this.template.trim();
        element.addEventListener('click', handleClick); // 事件委托
        return element;
      }
    }

    document.querySelector('#content').appendChild(new Navigation().render());
    routeChanged();
  </script>
</body>
</html>

示例二:表单提交处理

下面是一个实现表单提交处理的单页应用示例,演示了如何在组件中处理交互事件和业务逻辑。

<html>
<head>
  <title>Example SPA</title>
</head>
<body>
  <nav>
    <ul>
      <li><a href="/" class="link">Home</a></li>
      <li><a href="/about" class="link">About</a></li>
      <li><a href="/contact" class="link">Contact</a></li>
    </ul>
  </nav>
  <div id="content"></div>
  <script>
    // 定义路由表
    const routes = [
      { path: '/', component: Home },
      { path: '/about', component: About },
      { path: '/contact', component: Contact }
    ];

    // 监听路由变化
    window.addEventListener('popstate', routeChanged);

    // 路由跳转
    function navigateTo(path) {
      history.pushState(null, null, path);
      routeChanged();
    }

    // 路由变化处理函数
    function routeChanged() {
      const path = location.pathname;
      const route = routes.find(route => route.path === path) || {component: NotFound};
      document.querySelector('#content').innerHTML = new route.component().render();
    }

    // Home组件
    class Home {
      constructor() {
        this.template = `
          <h1>Welcome to Home Page</h1>
          <p>Home Page Content Here</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // About组件
    class About {
      constructor() {
        this.template = `
          <h1>About Us</h1>
          <p>About Us Content Here</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // Contact组件
    class Contact {
      constructor() {
        this.template = `
          <h1>Contact Us</h1>
          <p>Contact Us Content Here</p>
          <h2>Feedback Form</h2>
          <div id="form"></div>
        `;
      }

      render() {
        const element = document.createElement('div');
        element.innerHTML = this.template.trim();
        element.querySelector('#form').appendChild(new ContactForm().render());
        return element;
      }
    }

    // NotFound组件
    class NotFound {
      constructor() {
        this.template = `
          <h1>Not Found</h1>
          <p>404 Page Not Found</p>
        `;
      }

      render() {
        return this.template;
      }
    }

    // ContactForm组件
    class ContactForm {
      constructor() {
        this.template = `
          <form>
            <label>
              Name: <input type="text" name="name" required>
            </label>
            <label>
              Email: <input type="email" name="email" required>
            </label>
            <label>
              Message: <textarea name="message" rows="5" required></textarea>
            </label>
            <button type="submit">Submit</button>
          </form>
        `;
      }

      render() {
        const element = document.createElement('div');
        element.innerHTML = this.template.trim();
        element.querySelector('form').addEventListener('submit', handleSubmit);
        return element;
      }
    }

    // 提交处理函数
    function handleSubmit(event) {
      event.preventDefault();
      const formData = new FormData(event.target);
      const data = Object.fromEntries(formData.entries());
      console.log(data);
      // 处理提交数据...
      event.target.reset();
      alert('Submit success.');
    }

    // 定义事件处理函数
    function handleClick(event) {
      event.preventDefault();
      const path = event.target.href;
      navigateTo(path);
    }

    // Navigation组件
    class Navigation {
      constructor() {
        this.template = `
          <nav>
            <ul>
              <li><a href="/" class="link">Home</a></li>
              <li><a href="/about" class="link">About</a></li>
              <li><a href="/contact" class="link">Contact</a></li>
            </ul>
          </nav>
        `;
      }

      render() {
        const element = document.createElement('div');
        element.innerHTML = this.template.trim();
        element.addEventListener('click', handleClick); // 事件委托
        return element;
      }
    }

    document.querySelector('#content').appendChild(new Navigation().render());
    routeChanged();
  </script>
</body>
</html>

以上就是用原生JS做单页应用的详细攻略,希望对大家有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:用原生js做单页应用 - Python技术站

(1)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)

    JavaScript中最容易混淆的作用域、提升、闭包知识详解 作用域 JavaScript采用词法作用域,即函数的作用域在函数定义时就已经确定了,不会随着函数调用的位置改变。因此,JavaScript中存在全局作用域和函数作用域。 全局作用域 全局作用域是指在代码的任何位置都可以访问的变量、函数和对象,它是在所有函数外部定义的作用域。 以下是一个示例,全局作…

    JavaScript 2023年5月28日
    00
  • JavaScript 中使用SpreadJS导入和导出 Excel 文件的方法

    下面是详细的攻略。 JavaScript 中使用 SpreadJS 导入和导出 Excel 文件的方法 SpreadJS 是一款基于 JavaScript 的电子表格组件,支持 Excel 的导入和导出功能。本文将介绍如何使用 SpreadJS 的 API 对 Excel 文件进行导入和导出操作。 导入 Excel 文件 使用 SpreadJS 的 API …

    JavaScript 2023年6月11日
    00
  • 浅析js预加载/延迟加载

    浅析JS预加载/延迟加载 在Web开发中,常常需要在网页中引入JavaScript文件,但是如果JavaScript文件过大或者网络情况较差,就会出现网页加载速度过慢的问题,影响用户体验。为了解决这一问题,通常可以采用JS预加载和延迟加载技术。 JS预加载 JS预加载可以让网页在正式加载之前,提前加载部分必需的JS文件,从而提高网页的加载速度。可以通过以下方…

    JavaScript 2023年5月27日
    00
  • 用javascript来实现动画导航效果的代码

    当我们需要实现网站导航栏的动画效果时,我们可以使用 JavaScript 来完成。下面是详细的攻略及示例说明: 步骤一:创建 HTML 结构 我们需要创建HTML页面,并添加与导航栏有关的HTML标签,例如 nav、ul、li、a 等标签。这些标签应该与我们要展示的菜单项一致。 在此示例中,我们创建了一个简单的 HTML 结构代码: <nav> …

    JavaScript 2023年6月10日
    00
  • 从URL中提取参数与将对象转换为URL查询参数的实现代码

    从URL中提取参数的实现代码 通过JavaScript代码解析URL获取参数是一种很常见的操作,我们可以通过以下操作来提取URL中的参数: 1.使用window.location.search获取查询字符串部分,该部分包含了所有请求参数。例如,我们可以使用以下代码来获取URL地址中的search字符串: let searchStr = window.loca…

    JavaScript 2023年6月11日
    00
  • BootStrap+Mybatis框架下实现表单提交数据重复验证

    首先,我们需要明确一下实现表单提交数据重复验证的基本思路。我们可以在页面上的表单中增加一个校验码字段,每次提交时,先检测校验码,若校验码匹配成功则将表单数据保存至数据库,否则提示用户“数据已存在”。 下面是实现表单提交数据重复验证的完整攻略: 一、创建数据库表 我们可以先创建一个名为user的数据库表,用来存储用户表单提交数据。以下是该表的基本结构: CRE…

    JavaScript 2023年6月10日
    00
  • vue使用GraphVis开发无限拓展的关系图谱的实现

    Vue使用GraphVis开发无限拓展的关系图谱的实现 简介 GraphVis是一款基于JavaScript的网络可视化库,它支持将任何TCP/IP网络视为节点和边的集合,还支持关系网和流程图的绘制。在Vue项目中使用GraphVis可以方便地展示关系图谱,并且可以轻松实现拓展。 实现过程 步骤一:安装GraphVis库 可以使用npm命令来安装GraphV…

    JavaScript 2023年6月11日
    00
  • js获取url中的参数且参数为中文时通过js解码

    获取URL中的参数是前端开发中经常需要处理的场景之一。但如果参数中存在中文,获取并显示则需要特殊处理。 以下是获取URL参数且参数为中文时的完整攻略: 1.获取URL中的参数 我们可以使用JS内置对象window.location来获取当前页面的地址: var url = window.location.href; 接下来我们需要从url中解析出参数,一种常…

    JavaScript 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部