这是网上的实战课程,使用的技术栈有bower+less+angular1.x+gulp。没有涉及到后端,数据是模拟的json数据。

gulp

其中gulp的配置在这里。

less

关于less部分,只使用了一些最基础的语法。如下:

  • 文件引用

使用@import。

@import 'a.less';
@import 'b.less';
  • 定义变量

使用的了一个文件variabel.less专门用来定义变量。在less中定义变量使用@。定义完成后以分号结束

@defaultColor: #fff;
@defaultWidth: 400px;

这样在其他文件里,这要引入了这个文件,就可以使用这些变量。

@import 'variable.less';
body { color: @defaultColor; }
.Box { width: @defaultWidth; }
  • 样式的嵌套

&表示引用自己。

body {
  color: @defaultColor;
  .Box {
    background: red;
    &:hover {
      background: green;
    }
  }
}
  • unit函数

该函数用来删除或更换单位。
参数:

  1. dimension: 带单位或不带单位的数字。
  2. unit: (可选) 目标单位,如果省略此参数,则删除单位。
案例: unit(5,px)

输出: 5px

案例: unit(5em)

输出: 5
  • 函数
    定义一个函数,如下:
.pt(@px) {
  padding-top: unit(@px / 37.5,rem);
}

在使用的使用调用这个并传入参数即可。

.Box {
  .pt(20);
}

angular部分

angular使用的插件有:

  • angular-ui-router
  • angular-validation
  • angular-cookie
  • angular-animate
// app.js
angular.module('app',['ui.router','ngCookies','validation','ngAnimate'])

ui-router中,首先是定义路由,如下:

angular.module('app')
.config(['$stateProvider','$urlRouterProvider',function($stateProvider,$urlRouterProvider) {
  $stateProvider
  .state('main',{ // main是当前页面的id,以后要跳转到该页面使用ui-sref="main"或者$state.go('main');
    url: '/main',templateUrl: 'view/mian.html',controller: 'mainCtrl'
  })
  .state('login',{
    // 定义其他路由等
  })

  // 除了上述路由外,处理其他不匹配的路由
  $urlRouterProvider.otherwise('main');
}])

ui-sref

使用ui-router自带的ui-sref属性来定义将要跳转的页面的id。

<li ui-sref="main">跳转到main页面</li>

如果要传入参数,如下格式。()中的对象反映的是传入的参数键值对。

<li ui-sref="position({id: item.id})">跳转到position页面</li>

在position页面对应的控制器中,通过$state.params.id取得查询键。

angular.module('app')
.controller('positionCtrl',['$http','$state','$scope',function($http,$state,$scope) {
  $http.get('data/position.json',{
    params: {
      id: $state.params.id
    }
  })
  .then(function() {},function() {})
}])

可以通过ui-sref-active给选中的标签添加样式。比如菜单栏。

指令中的scope

关于指令中的scope请看这里,内容较多,我单独列了出来。

$index/$last

在使用ng-repeat渲染元素时,可以使用两个内置的属性观察渲染情况。$scope.$index来查看渲染的子元素的索引,$scope.$last(boolean)来查看是否执行完成,如果是true,表示ng-repeat执行完毕。

<button ng-click="showPositionList($index)" ng-repeat="cls in com.positionClass" ng-bind="cls.name"></button>

这个类似于导航栏的按钮,点击后控制器拿到这个$index,根据不同的$index传递给view层不同的数据。

$id/$parent$root

在任何一个控制器中,通过$scope.$id$scope.$parent$scope.$root来表示当前作用域的id,父作用域,根作用域。

通常在angular应用的run方法中定义根作用域相关属性。

angular.module('app',[]) // 必须引入ng-route
//config方法在整个页面中最先执行,先于run,
.config(['$stateProvider',$urlRouterProvider) {
  // 在这里配置路由
}])
// 通常将路由事件定义在根作用域下
.run(function($rootScope) {
//console.log($rootScope);
  $rootScope.$on('$routeChangeStart',function () {
    console.log(this)
    console.log(arguments);
  })
})

value()和constant()

使用constant()来保存一个常量。
使用value()函数来缓存全局变量(需要的时候可以直接使用)。

constant()和value()方法之间一个最主要的区别是,常量可以注入到配置函数(.config())中,而值不行。

angular.module('app')
.constant('apikey','real')
angular.module('app')
.value('dict',{}) // 缓存全局变量
.run(['dict','$http',function(dict,$http) {
  $http.get('data/city.json').then(function(res) {
    dict.city = res.data;
  })
  $http.get('data/salary.json').then(function(res) {
    dict.salary = res.data;
  })
  $http.get('data/scale.json').then(function(res) {
    dict.scale = res.data;
  })
}])

自定义过滤器

<!--过滤item-->
<li ng-repeat="item in data | filterByObj:filterObj">

filterByObj是一个已经定义好的过滤器。它返回的函数中有两个参数,第一个list表示上述的data,第二个obj表示filterByObj:后面的filterObj。这个filterObj对应父作用域的一个属性,根据情况而改变。从而达到筛选效果。

angular.module('app')
.filter('filterByObj',[function() {
  return function(list,obj) {
      var result = [];
      angular.forEach(list,function(item) {
        var isEqual = true;
        for(var e in obj) {
          if(item[e] !== obj[e]) {
            isEqual = false;            
          }
        }
        if(isEqual) {
          result.push(item);
        }
      })

      return result;
  }
}])

$interval

var interval = $interval(fn,timedelay)
$inteval.cancel(interval); // 使用cancel取消这个定时器
// 在原生js中是interval = null;

阻止冒泡

ng-click事件有一个事件对象$eventstopPropagation不需要加括号。

<li ng-click="$event.stopPropagation;select(item);"></li>

$watch

如果在指令中用到了某个属性,但是这个属性的值依赖于异步返回的结果,这时候就需要$watch这个值。否则报错。

// 1 父作用域
<div app-company com="company"></div>
// 这是副作用域控制器执行的
$http.get('data/company.json?id='+id).then(function(res){
  $scope.company = res.data;
})

// 2
angular.module('app')
.directive('appPositionClass',[function() {
  return {
    restrict: 'A',replace: true,templateUrl: 'view/template/positionClass.html',scope: {
      com: '='
    },link: function($scope,element,attr) {
      $scope.$watch('com',function(newVal,oldVal,scope) {
        if(newVal){
          $scope.showPositionList(0);
        }
      })
    }
  }
}])

可以看到指令要想获得com属性,依赖于父作用域的$scope.company。而通过一个异步操作才能返回。所以指令中就$watch这个变量。

angular-validation

首先在index.html页面中引入angular-validation.js,然后再angular.module(‘app’,[‘validation’])加上依赖。

这个插件定义了一个$validationProvider服务。用来设置表达式和验证消息。

// validation.js
angular.module('app')
.config(['$validationProvider',function($validationProvider) {
  var expression = {
    phone: /^1\d{10}$/,password: function(value) {
      return value.length > 5;
    },required: function(value) {
      return !!value;
    }
  }
  var defaultMsg = {
    phone: {
      success: '',error: '11位手机号'
    },password: {
      success: '',error: '长度至少6位'
    },required: {
      success: '',error: '不能为空'
    }
  }

  $validationProvider.setExpression(expression).setDefaultMsg(defaultMsg);
}])

在login页面中,做了简单的验证。

<div class="login">
  <form class="d-b ta-c" name="form">
    <div class="form-line ta-l p-r">
      <span class="icon account va-t d-ib"></span>
      <input name="phone" validator="required,phone" ng-model="user.phone" class="d-ib" type="text" placeholder="输入手机号">
    </div>
    <div class="form-line ta-l p-r">
      <span class="icon lock va-t d-ib"></span>
      <input name="password" validator="required,password" ng-model="user.password" class="d-ib" type="password" placeholder="输入密码">
    </div>
    <button class="login-btn" validation-submit="form" ng-click="submit();">登录</button>
    <button class="register-btn" ui-sref="register">注册</button>
  </form>
</div>

注意inputvalidator属性,这里是验证的表达式的内容,如果有多个,使用逗号隔开。这个内容对应validation.js中的var expression中的键。
注意<button validation-submit="form" ng-click="submit"></button>这里,form是表单的name属性。

factory/service

我们使用factory或者service定义服务。service使用this来保存服务内容,类似构造函数。而factory使用返回值来保存服务内容。我们定义了一个cache服务。$cookiesangular-cookies插件提供的。两种写法如下:

// app.js中
angular.module('app','ngAnimate']);

服务:

angular.module('app')
.service('cache',['$cookies',function($cookies) {
  this.put = function(key,value) {
    $cookies.put(key,value);
  };
  this.get = function(key) {
    return $cookies.get(key);
  };
  this.remove = function(key) {
    return $cookies.remove(key);
  }
}])
angular.module('app')
.factory('cache',function($cookies) {
  return {
    put: function(key,value) {
      $cookies.put(key,value);
    },get: function(key) {
      return $cookies.get(key);
    },remove: function(key) {
      return $cookies.remove(key);
    }
  }
}])

讲真,我觉得使用这个不如使用localStorage,简单快捷(涉及到sessionID用cookie?)。

装饰器

装饰器是非常强大的,它不仅可以应用在我们的我们自己的服务上,也可以对AngularJS的核心服务进行拦截、中断甚至替换功能的操作。事实上AngularJS中很多功能的测试就是借助$provide.decorator()建立的。

由于这个项目没有后端,为了模拟post请求,我们需要修改$http内置的post请求。

angular.module('app')
.config(['$provide',function($provide) {
  $provide.decorator('$http',['$delegate','$q',function($delegate,$q) {
    $delegate.post = function(url,data,config) {
      var def = $q.defer();
      $delegate.get(url).then(function(res) {
        def.resolve(res.data);
      },function(err) {
        def.reject(err);
      })

      return {
        success: function(cb) {
          def.promise.then(cb);
        },error: function(cb) {
          def.promise.then(null,cb);
        }
      }
    }

    return $delegate;
  }])
}])

decorator()函数可以接受两个参数。

  • name (字符串)将要拦截的服务名称
  • decoratorFn(函数)在服务实例化时调用该函数,这个函数由injector.invoke调用,可以将服务注入这个函数中。

$delegate是可以进行装饰的最原始的服务,为了装饰其他服务,需要将其注入进装饰器。

$q

内置的$q服务用来在Angular中创建promise。如上所述,我们使用$q.deffer()创建一个延迟对象def。通常返回时通过return def.promise得到一个promise对象。这里更进一步封装了。

上述的def使用了两种方法,分别是:

  • def.resolve(data)
  • def.reject(err)
  • def.notify(data) 上述未提到

如果返回值是def.promise,它的then方法有三个参数。

var promise = $http.post(someurl);
promise.then(function(data) {
  alert('success');
},funciton(err) {
  alert('Failed');
},function(dataUpdate) {
  alert('update')
})

更加详细的在:
浅谈Angular的 $q,defer,promise

总结

github地址

晚上花了几个小时写了总结,学完这个项目之后,确实学到了很多。在写博客的过程中,为了表述完全,又特定找了一些资料,看以前的代码。更加深了理解。

从今以后,每写一个项目都要做一次总结。

angularjs仿拉勾网webapp总结与记录的更多相关文章

  1. 详解如何通过H5(浏览器/WebView/其他)唤起本地app

    这篇文章主要介绍了详解如何通过H5(浏览器/WebView/其他)唤起本地app的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. H5混合开发app如何升级的方法

    本篇文章主要介绍了H5混合开发app如何升级的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  3. html5唤起app的方法

    这篇文章主要介绍了html5唤起app的方法的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. xcode – 上传到App Store时进行身份验证

    只需为现有安装/文件夹创建备份,这很重要,因为在(新)安装期间,Transporter将删除以前的安装:现在运行以下命令来更新Transporter:希望这有助于某人.

  5. App store拒绝应用程序在iOs 10上支持IPV6网络

    我收到苹果公司的app拒绝邮件,下面是我们在连接到IPv6网络的Wi-Fi上运行iOS10.0.2的iPad和iPhone上查看了应用中的一个或多个错误.具体来说,应用程序在启动时仍保留在启动屏根据他们的要求,我已经在我的Mac上创建了NAT64网络,并为iPhone5S设备10.0.2os版本共享了互联网,App工作正常,但苹果称其不与IPv6合作任何人都可以确认我需要检查其他什么吗?

  6. ios – 我如何从iPhone中提取IPA以从App Store下载以便我可以在IPA中查看资产?

    我最喜欢的应用程序之一已从应用程序商店中删除,我想因为它没有在太长时间内更新.我有一台旧设备,但没有下载到我的新手机上.如何获得IPA以便我可以查看应用程序包并查看应用程序中的资产?

  7. ios – – [Not A Type _cfTypeID]:发送到解除分配的实例的消息

    我正在使用代码为图像提供不同的效果,如对比度,色调,饱和度等;并使用了appleglImageProcessing代码,我从我的视图跳转到glimgeProcessing,并将结果图像保存到appDelegate文件中的uiimage属性.从Eagle视图返回后,我使用viewDidAppear函数将我的图像视图更改为更新的图像我的代码是我的日志响应是尝试将图像设置为我的imageView时出现问

  8. iOS扩展:是否需要增加其捆绑版本(CFBundleVersion)?

    我是否必须在我的扩展程序的Info.plist中增加CFBundLeversion以确保它覆盖现有的?或者,如果在主应用程序的Info.plist中这样做就足够了?

  9. ios – navigator.app undefined

    谢谢你的帮助.干杯,米格尔解决方法“navigator.app”对象仅适用于Android.幸运的是,在即将发布的PhoneGap2.3.0版本中你可以做到:做你想做的事.

  10. 验证Xcode安装时,“/Applications/Xcode.app:密封资源丢失或无效”错误

    你认为我需要重新安装Xcode以防万一?

随机推荐

  1. Angular2 innerHtml删除样式

    我正在使用innerHtml并在我的cms中设置html,响应似乎没问题,如果我这样打印:{{poi.content}}它给了我正确的内容:``但是当我使用[innerHtml]=“poi.content”时,它会给我这个html:当我使用[innerHtml]时,有谁知道为什么它会剥离我的样式Angular2清理动态添加的HTML,样式,……

  2. 为Angular根组件/模块指定@Input()参数

    我有3个根组件,由根AppModule引导.你如何为其中一个组件指定@input()参数?也不由AppModalComponent获取:它是未定义的.据我所知,你不能将@input()传递给bootstraped组件.但您可以使用其他方法来做到这一点–将值作为属性传递.index.html:app.component.ts:

  3. angular-ui-bootstrap – 如何为angular ui-bootstrap tabs指令指定href参数

    我正在使用角度ui-bootstrap库,但我不知道如何为每个选项卡指定自定义href.在角度ui-bootstrap文档中,指定了一个可选参数select(),但我不知道如何使用它来自定义每个选项卡的链接另一种重新定义问题的方法是如何使用带有角度ui-bootstrap选项卡的路由我希望现在还不算太晚,但我今天遇到了同样的问题.你可以通过以下方式实现:1)在控制器中定义选项卡href:2)声明一个函数来改变控制器中的散列:3)使用以下标记:我不确定这是否是最好的方法,我很乐意听取别人的意见.

  4. 离子框架 – 标签内部的ng-click不起作用

    >为什么标签标签内的按钮不起作用?>但是标签外的按钮(登陆)工作正常,为什么?>请帮我解决这个问题.我需要在点击时做出回复按钮workingdemo解决方案就是不要为物品使用标签.而只是使用divHTML

  5. Angular 2:将值传递给路由数据解析

    我正在尝试编写一个DataResolver服务,允许Angular2路由器在初始化组件之前预加载数据.解析器需要调用不同的API端点来获取适合于正在加载的路由的数据.我正在构建一个通用解析器,而不是为我的许多组件中的每个组件设置一个解析器.因此,我想在路由定义中传递指向正确端点的自定义输入.例如,考虑以下路线:app.routes.ts在第一个实例中,解析器需要调用/path/to/resourc

  6. angularjs – 解释ngModel管道,解析器,格式化程序,viewChangeListeners和$watchers的顺序

    换句话说:如果在模型更新之前触发了“ng-change”,我可以理解,但是我很难理解在更新模型之后以及在完成填充更改之前触发函数绑定属性.如果您读到这里:祝贺并感谢您的耐心等待!

  7. 角度5模板形式检测形式有效性状态的变化

    为了拥有一个可以监听其包含的表单的有效性状态的变化的组件并执行某些组件的方法,是reactiveforms的方法吗?

  8. Angular 2 CSV文件下载

    我在springboot应用程序中有我的后端,从那里我返回一个.csv文件WheniamhittingtheURLinbrowsercsvfileisgettingdownloaded.现在我试图从我的角度2应用程序中点击此URL,代码是这样的:零件:服务:我正在下载文件,但它像ActuallyitshouldbeBook.csv请指导我缺少的东西.有一种解决方法,但您需要创建一个页面上的元

  9. angularjs – Angular UI-Grid:过滤后如何获取总项数

    提前致谢:)你应该避免使用jQuery并与API进行交互.首先需要在网格创建事件中保存对API的引用.您应该已经知道总行数.您可以使用以下命令获取可见/已过滤行数:要么您可以使用以下命令获取所选行的数量:

  10. angularjs – 迁移gulp进程以包含typescript

    或者我应该使用tsc作为我的主要构建工具,让它解决依赖关系,创建映射文件并制作捆绑包?

返回
顶部