一、安装gulp(已经安装了node环境)
npm install -g gulp
二、在package.json文件中配置依赖插件
{ "name": "xxxx", "version": "0.0.0", "private": true, "scripts": { "start": "node ./bin/www" }, "devDependencies": { "del": "^2.2.0", "gulp": "^3.9.1", "gulp-autoprefixer": "^3.1.0", "gulp-cache": "^0.4.5", "gulp-compass": "^2.1.0", "gulp-concat": "^2.6.0", "gulp-imagemin": "^3.0.1", "gulp-jshint": "^2.0.1", "gulp-livereload": "^3.8.1", "gulp-minify-css": "^1.2.4", "gulp-notify": "^2.2.0", "gulp-rename": "^1.2.2", "gulp-requirejs": "^0.1.3", "gulp-requirejs-optimize": "^1.0.0", "gulp-sass": "^2.3.2", "gulp-sourcemaps": "^1.6.0", "gulp-uglify": "^1.5.3" } }
注:devDependencies里可以注册你要包含的插件以及相应的版本
三、安装这些插件
npm install (如果想单独安装某个插件 npm install --save-dev gulp-uglify@version)
四、配置gulpfile.js文件
var gulp = require('gulp'), sass = require('gulp-sass'), compass = require('gulp-compass'), autoprefixer = require('gulp-autoprefixer'), minifycss = require('gulp-minify-css'), jshint = require('gulp-jshint'), uglify = require('gulp-uglify'), imagemin = require('gulp-imagemin'), rename = require('gulp-rename'), concat = require('gulp-concat'), notify = require('gulp-notify'), cache = require('gulp-cache'), livereload = require('gulp-livereload'), del = require('del'), sourcemaps = require('gulp-sourcemaps'), requirejsOptimize=require('gulp-requirejs-optimize'); gulp.task('styles', function() { return gulp.src('public/stylesheets/src/*.scss') .pipe(sass({outputStyle: 'expanded'}).on('error', sass.logError)) .pipe(sourcemaps.init()) .pipe(autoprefixer('last 2 version')) .pipe(sourcemaps.write()) .pipe(gulp.dest('public/stylesheets/dist')) .pipe(rename({suffix: '.min'})) .pipe(minifycss()) .pipe(gulp.dest('public/stylesheets/dist')) .pipe(notify({ message: 'Styles task complete' })); //.pipe(browserSync.reload({stream: true})); }); gulp.task('scripts', function() { return gulp.src('public/javascripts/src/**/*.js') // .pipe(jshint('.jshintrc')) // .pipe(jshint.reporter('default')) .pipe(requirejsOptimize({ mainConfigFile: 'public/javascripts/src/config.js', //optimize: 'none', optimize: 'none', exclude: [ 'angular', 'angularRoute', 'angularMocks', 'text', 'ngFileUpload', 'routeStyles', 'uediter', 'ueditorConfig', 'ueditorAll', 'pagination' ] })) .pipe(gulp.dest('public/javascripts/dist')) .pipe(rename({suffix: '.min'})) .pipe(uglify()) .pipe(gulp.dest('public/javascripts/dist')) .pipe(notify({ message: 'Scripts task complete' })); }); gulp.task('images', function() { return gulp.src('public/images/src/**/*') .pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true }))) .pipe(gulp.dest('public/images/dist')) .pipe(notify({ message: 'Images task complete' })); }); gulp.task('clean', function(cb) { del(['public/stylesheets/dist', 'public/javascripts/dist', 'public/images/dist'], cb) }); gulp.task('blog',function() { gulp.start('styles', 'scripts', 'images'); }); gulp.task('watch', function() { // Watch .scss files gulp.watch('public/stylesheets/src/**/*.scss', ['styles']); // Watch .js files gulp.watch('public/javascripts/src/**/*.js', ['scripts']); // Watch image files gulp.watch('public/images/src/**/*', ['images']); livereload.listen(); // Watch any files in dist/, reload on change gulp.watch(['public/stylesheets/dist', 'public/javascripts/dist', 'public/images/dist']).on('change', livereload.changed); });
注:以上为比较直观简单的配置,可以使用gulp-load-plugin插件进一步优化该文件,相关插件功能可以访问官网查看相关的信息
五、angular + requirejs 使用
1、首先看下js文件的目录结构
2、看下main.js文件的内容
require.config({ paths: { angular: '../lib/angular/angular', angularRoute: '../lib/angular-route/angular-route', angularMocks: '../lib//angular-mocks/angular-mocks', text: '../lib/requirejs-text/text', ngFileUpload:'../lib/ng-file-upload/ng-file-upload', routeStyles:'../lib/angular-route-styles/route-styles', ueditorConfig:'../lib/ueditor/ueditor.config', ueditorAll:'../lib/ueditor/ueditor.all', uediter:'../lib/angular-ueditor/dist/angular-ueditor', pagination:'../lib/angularjs-pagination/src/ng-pagination' }, shim: { 'angular' : {'exports' : 'angular'}, 'angularRoute': ['angular'], 'angularMocks': { deps:['angular'], 'exports':'angular.mock' } , 'ngFileUpload': ['angular'], 'routeStyles':['angular'], 'uediter':['ueditorConfig','ueditorAll','angular'], 'pagination':['angular'] }, priority: [ "angular" ] }); //http://code.angularjs.org/1.2.1/docs/guide/bootstrap#overview_deferred-bootstrap window.name = "NG_DEFER_BOOTSTRAP!"; require( [ 'angular', 'app', 'routes' ], function(angular, app, routes) { 'use strict'; var $html = angular.element(document.getElementsByTagName('html')[0]); angular.element().ready(function() { angular.resumeBootstrap([app['name']]); }); });
3、看下app.js文件内容
define([ 'angular', 'filters', 'services', 'directives', 'controllers', 'angularRoute', 'ngFileUpload', 'routeStyles', 'pagination', 'uediter' ], function (angular, filters, services, directives, controllers) { 'use strict'; // Declare app level module which depends on filters, and services return angular.module('myApp', [ 'ngRoute', 'ngFileUpload', 'ng.ueditor', 'routeStyles', 'ng-pagination', 'myApp.controllers', 'myApp.filters', 'myApp.services', 'myApp.directives' ], function($httpProvider) { // Use x-www-form-urlencoded Content-Type $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'; /** * The workhorse; converts an object to x-www-form-urlencoded serialization. * @param {Object} obj * @return {String} */ var param = function(obj) { var query = '', name, value, fullSubName, subName, subValue, innerObj, i; for(name in obj) { value = obj[name]; if(value instanceof Array) { for(i=0; i<value.length; ++i) { subValue = value[i]; fullSubName = name + '[' + i + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if(value instanceof Object) { for(subName in value) { subValue = value[subName]; fullSubName = name + '[' + subName + ']'; innerObj = {}; innerObj[fullSubName] = subValue; query += param(innerObj) + '&'; } } else if(value !== undefined && value !== null) query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; } return query.length ? query.substr(0, query.length - 1) : query; }; // Override $http service's default transformRequest $httpProvider.defaults.transformRequest = [function(data) { return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data; }]; }); });
4、路由文件routes.js文件下内容
define(['angular', 'app'], function(angular, app) { 'use strict'; return app.config(['$routeProvider',function($routeProvider) { $routeProvider.when('/', { templateUrl: 'templates/main.html',//加载的模版 controller: 'index' ,//加载的控制器 css: 'stylesheets/dist/index.css'//加载的样式 }); $routeProvider.otherwise({redirectTo: '/'}); }]); });
5、控制器 (以下以分页服务为例子 )
(1)controllers文件内容
define(['angular', 'services'], function (angular) { 'use strict'; /* Controllers */ return angular.module('myApp.controllers', ['myApp.services']) // Sample controller where service is being used .controller('index', ['$scope', '$injector', function ($scope, $injector) { require(['controllers/index'], function(index) { // injector method takes an array of modules as the first argument // if you want your controller to be able to use components from // any of your other modules, make sure you include it together with 'ng' // Furthermore we need to pass on the $scope as it's unique to this controller $injector.invoke(index, this, {'$scope': $scope}); }); }]) });
(2)index文件下内容
define([], function() { return ['$scope', '$http','$sce', 'pagination',function($scope, $http, $sce,pagination) { // You can access the scope of the controller from here $scope.posts = []; var getPosts= function () { var postData = { page: 1, pageSize: 10 } var url = '/main' pagination.list($http,url,postData).success(function (response) { console.log(response); // $scope.paginationConf.totalItems = response.total; $scope.posts = angular.forEach(angular.fromJson(response.posts), function (post) { post.post = $sce.trustAsHtml(post.post); }); }); } getPosts(); $scope.onPageChange = function() { // ajax request to load data console.log($scope.currentPage); }; // set pagecount in $scope $scope.pageCount = 100; //配置分页基本参数 /*************************************************************** 当页码和页面记录数发生变化时监控后台查询 如果把currentPage和itemsPerPage分开监控的话则会触发两次后台事件。 ***************************************************************/ // $scope.$watch('paginationConf.currentPage + paginationConf.itemsPerPage', getPosts); // because this has happened asynchroneusly we've missed // Angular's initial call to $apply after the controller has been loaded // hence we need to explicityly call it at the end of our Controller constructor $scope.$apply(); }]; });
6、服务(没有找到方法实现按需加载 如果有好的的方法实现像控制器那样按需加载 请留言给我 感激不尽,谢谢)
(1)services文件内容
define(['angular','require','services/pagination'], function (angular,require) { 'use strict'; /* Services */ // Demonstrate how to register services // In this case it is a simple value service. angular.module('myApp.services', []) .value('version', '0.1') .factory('pagination',function () { return require('services/pagination'); }) });
(2)pagination文件下内容
define([], function() { var list = function ($http,url,postData) { return $http.post(url, postData); } return { list: function ($http,url,postData) { return list($http,url,postData); } } });
7、指令和过滤器实现和服务实现事一样的
(1)directives文件下内容
define(['angular', 'services'], function(angular, services) { 'use strict'; /* Directives */ angular.module('myApp.directives', ['myApp.services']) .directive('appVersion', ['version', function(version) { return function(scope, elm, attrs) { elm.text(version); }; }]); });
(2)filters文件内容
define(['angular', 'services'], function (angular, services) { 'use strict'; /* Filters */ angular.module('myApp.filters', ['myApp.services']) .filter('interpolate', ['version', function(version) { return function(text) { return String(text).replace(/\%VERSION\%/mg, version); }; }]); });
(注:如果有更好的实现方式或错误 请留言给我 或 demo地址给我 谢谢)
未完待续(angular 深入理解和开发)