利用require.js与angular搭建spa应用的方法实例


Posted in Javascript onJuly 19, 2017

前言

AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购。是一款优秀的前端JS框架,已经被用于Google的多款产品当中。AngularJS有着诸多特性,最为核心的是:MVVM、模块化、自动化双向数据绑定、语义化标签、依赖注入等等。

本文是接上篇,angular 实战部分,angular比较适合spa项目,这里不借助任何seed和构建工具,直接从零搭建,基本的angular项目结构大致包含如下几个部分:

1)app.js 入口

2)index.html html框架页

3)lib(vendor)第三方类库

4)components 业务组件

5)styles/images 静态资源部分

1、常规实现

创建文件夹demo1,按照上述结构分别创建app.js ,index.html文件,创建lib、components、styles和images文件夹,最终如下图所示:

利用require.js与angular搭建spa应用的方法实例

在此基础上,我们增加三个业务组件home,about,contact,并初始化基本代码如下:

利用require.js与angular搭建spa应用的方法实例

核心代码文件

index.html

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>demo1</title>
 <script src="https://cdn.bootcss.com/angular.js/1.6.0/angular.js"></script>
 <script src="https://cdn.bootcss.com/angular-ui-router/1.0.3/angular-ui-router.js"></script>

 <script src='./app.js'></script>
 <script src='./components/home/home.controller.js'></script>
 <script src='./components/about/about.controller.js'></script>
 <script src='./components/contact/contact.controller.js'></script>

</head>
<body>
 <div class="nav">
 <ul>
  <li><a ui-sref="home">Home</a></li>
  <li><a ui-sref="about">About</a></li>
  <li><a ui-sref="contact">Contact</a></li>
 </ul>
 </div>
 <div class="container">
 <div ui-view></div>
 </div>
</body>
</html>

app.js

angular.module('app', ['ui.router'])
 .config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
 //默认指向
 $urlRouterProvider.otherwise('/home');

 $stateProvider.state('home', {
  url: '/home',
  templateUrl: './components/home/home.tpl.html',
  controller: 'HomeController',
  controllerAs: 'vm'

 }).state('about', {
  url: '/about',
  templateUrl: './components/about/about.tpl.html',
  controller: 'AboutController',
  controllerAs: 'vm'
 }).state('contact', {
  url: '/contact',
  templateUrl: './components/contact/contact.tpl.html',
  controller: 'ContactController',
  controllerAs: 'vm'
 })

 }])

controller中文件格式一直,tpl为view文件以home模块为例:

home.controller.js

angular.module('app')
 .controller('HomeController', HomeController);

HomeController.$inject = ['$scope'];

function HomeController($scope) {
 console.log("HomeController created successfully!!!");
}

home.tpl.html

<h2>Page Home</h2>

对命名做如下规定,所有文件夹都用小写,多词用点号隔开,所有文件都小写,多词用点号分割,控制器以.controller.js结尾,类似的有.service.js,.tpl.html,.directive.js,.filter.js等。

最终运行效果如下:

利用require.js与angular搭建spa应用的方法实例

上述代码能正常运行,但是我们发现一个问题,当前js文件或者说模块较少,我们引入不会有很大的问题,但是当我们的应用变得很大,文件几十甚至上百个,如何处理呢,有人说当然使用构建工具了,一个一个引入多慢呢,构建工具当然可以做到批量引入js文件,但是我们还需要考虑按需加载的问题,举例来说,我们在打开home的时候,about和contact是没必要加载的,但是按照我们传统的模式,所有脚本都完成了加载,这首先增加了http请求次数,脚本过多的加载解析也影响浏览器的渲染,用户体验并不友好,基于此,我们有几种方式来实现,1、基于requirejs来做,这也是本章内容要讲的部分;2、使用webpack分块打包,实现按需加载,后期看时间会加入对应的文章;3、使用oclazyload(可自行google)。本文就以requirejs来实现一下业务模块的按需加载,在此之前首先引入requirejs。

2、引入Requirejs

RequireJS 是一个JavaScript模块加载器。它非常适合在浏览器中使用,但它也可以用在其他脚本环境,就像 Rhino and Node。使用RequireJS加载模块化脚本将提高代码的加载速度和质量,实现的是AMD规范,当然类似的还有CMD规范的实现框架seajs。

Requirejs中,简单的说一个文件一个模块,即是单文件模块,所以对模块的加载其实本质上是对文件的加载。

假设读者已经了解requirejs的基本使用方式。

上一节中,讲到了提了一下controller的注册方式,其中说到了动态注册,当然除了controller之外,还有service、directive等都可以实现动态注册,这也是我们实现按需加载的基础,现在对我们的项目做一下修改,增加requirejs配置文件,main.js

require.config({
 paths:{
 angular:'https://cdn.bootcss.com/angular.js/1.6.0/angular',
 ui_router:'https://cdn.bootcss.com/angular-ui-router/1.0.3/angular-ui-router',
 app:'./app'
 
 },
 shim:{
 angular:{exports:'angular'}
 }
});

require(['angular','./app','ui_router'],function(angular,app){
 angular.element(document).ready(function(){
 angular.bootstrap(document,[app.name]);
 })
})

app.js修改如下:

define(['angular', 'ui_router'], function (angular) {
 var app = angular.module('app', ['ui.router'])
 .config(['$controllerProvider', '$provide', function ($controllerProvider, $provide) {
  app.register = {
  controller: $controllerProvider.register,//动态注册controller
  factory: $provide.factory//动态注册服务
  }
 }])
 .config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
  //默认指向
  $urlRouterProvider.otherwise('/home');

  $stateProvider.state('home', {
  url: '/home',
  templateUrl: './components/home/home.tpl.html',
  controller: 'HomeController',
  controllerAs: 'vm',
  resolve: {
   deps: loadCtrl(['./components/home/home.controller'])
  }

  }).state('about', {
  url: '/about',
  templateUrl: './components/about/about.tpl.html',
  controller: 'AboutController',
  controllerAs: 'vm',
  resolve: {
   deps: loadCtrl(['./components/about/about.controller'])
  }
  }).state('contact', {
  url: '/contact',
  templateUrl: './components/contact/contact.tpl.html',
  controller: 'ContactController',
  controllerAs: 'vm',
  resolve: {
   deps: loadCtrl(['./components/contact/contact.controller'])
  }
  })

 }]);
 return app;


 function loadCtrl(path_arr) {
 return ['$q','$rootScope', function ($q,$rootScope) {
  var defered = $q.defer();
  require(path_arr, function () {





$rootScope.$apply(function(){














deffered.resolve();






})
49  });

  return defered.promise;

 }]
 };
})

修改controller注册方式如下:

define(['app'], function (app) {
 app.register.controller('HomeController', HomeController);

 HomeController.$inject = ['$scope'];

 function HomeController($scope) {
 console.log("HomeController created successfully!!!");
 }
})

最后修改修改index.html中脚本引入方式,以及去掉ng-app指令启动方式,angular应用启动已在main.js中通过domready后使用脚本启动。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>demo1</title>
 <script src="https://cdn.bootcss.com/require.js/2.3.3/require.js" data-main="./main"></script>

</head>
<body>
 <div class="nav">
 <ul>
  <li><a ui-sref="home">Home</a></li>
  <li><a ui-sref="about">About</a></li>
  <li><a ui-sref="contact">Contact</a></li>
 </ul>
 </div>
 <div class="container">
 <div ui-view></div>
 </div>
</body>
</html>

最终运行效果如下,可以看到只有在点击了对应的菜单时,才加载了对应的controller:

利用require.js与angular搭建spa应用的方法实例

由于代码简单,注释很少,有疑问可直接提交。

总结

以上就是这篇文章的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
JavaScript CSS修改学习第三章 修改样式表
Feb 19 Javascript
JS文本框默认值处理详解
Jul 10 Javascript
html向js方法传递参数具体实现
Aug 08 Javascript
Jquery中children与find之间的区别详细解析
Nov 29 Javascript
不要使用jQuery触发原生事件的方法
Mar 03 Javascript
解决js下referer兼容各大浏览器的方法
Nov 03 Javascript
AngularJS修改model值时,显示内容不变的实例
Sep 13 Javascript
Element Input组件分析小结
Oct 11 Javascript
详解使用React.memo()来优化函数组件的性能
Mar 19 Javascript
Koa 中的错误处理解析
Apr 09 Javascript
微信小程序 获取手机号 JavaScript解密示例代码详解
May 14 Javascript
微信小程序实现可长按移动控件
Nov 01 Javascript
ztree简介_动力节点Java学院整理
Jul 19 #Javascript
Angular 1.x个人使用的经验小结
Jul 19 #Javascript
纯js实现的积木(div层)拖动功能示例
Jul 19 #Javascript
vue loadmore组件上拉加载更多功能示例代码
Jul 19 #Javascript
vue引入swiper插件的使用实例
Jul 19 #Javascript
vue loadmore 组件滑动加载更多源码解析
Jul 19 #Javascript
JS实现的走迷宫小游戏完整实例
Jul 19 #Javascript
You might like
PHP中iconv函数转码时截断字符问题的解决方法
2015/01/21 PHP
CI框架常用方法小结
2016/05/17 PHP
php好代码风格的阶段性总结
2016/06/25 PHP
PHP实现的简单操作SQLite数据库类与用法示例
2017/06/19 PHP
谷歌浏览器 insertCell与appendChild的区别
2009/02/12 Javascript
一个关于jqGrid使用的小例子(行按钮)
2011/11/04 Javascript
js多级树形弹出一个小窗口层(非常好用)实例代码
2013/03/19 Javascript
不使用浏览器运行javascript代码的方法
2013/07/24 Javascript
JS 去除Array中的null值示例代码
2013/11/20 Javascript
jQuery插件slides实现无缝轮播图特效
2015/04/17 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
2015/06/01 Javascript
jQuery模拟物体自由落体运动(附演示与demo源码下载)
2016/01/21 Javascript
javascript的正则匹配方法学习
2016/02/24 Javascript
基于javascript实现泡泡大冒险网页版小游戏
2016/03/23 Javascript
省市选择的简单实现(基于zepto.js)
2016/06/21 Javascript
微信小程序-拍照或选择图片并上传文件
2017/01/06 Javascript
微信小程序开发之选项卡(窗口底部TabBar)页面切换
2017/04/12 Javascript
Angular PWA使用的Demo示例
2019/01/31 Javascript
vue 解决异步数据更新问题
2019/10/29 Javascript
js实现抽奖功能
2020/11/24 Javascript
用javascript实现倒计时效果
2021/02/09 Javascript
Python中对象迭代与反迭代的技巧总结
2016/09/17 Python
Python使用sklearn实现的各种回归算法示例
2019/07/04 Python
Python 生成一个从0到n个数字的列表4种方法小结
2019/11/28 Python
详解python模块pychartdir安装及导入问题
2020/10/22 Python
python爬取抖音视频的实例分析
2021/01/19 Python
如何利用XMLHTTP检测URL及探测服务器信息
2013/11/10 面试题
手术室护士自我鉴定
2013/10/14 职场文书
通用求职信范文模板分享
2013/12/27 职场文书
招聘与培训专员岗位职责
2014/01/30 职场文书
个人房屋买卖协议书(范本)
2014/10/04 职场文书
2015元旦晚会主持词(开场白+结束语)
2014/12/14 职场文书
2014年社区卫生工作总结
2014/12/18 职场文书
蜗居观后感
2015/06/11 职场文书
二年级数学教学反思
2016/02/16 职场文书
redis配置文件中常用配置详解
2021/04/14 Redis