-
Notifications
You must be signed in to change notification settings - Fork 1
angularjs
- 1 简介
- 2 配置
- 3 注意
- 4 angualr js 笔记
- 5 常用指令
- 6 常见问题
- 7 常见错误说明
路由、模板交给 angular 处理
注
以下实践记录中
- 新加的记录后面加着
##
- 修改的记录后面加着
#*
AngularJS 指令是扩展的 HTML 属性,带有前缀 ng-
- ng-bind 是从 $scope -> view 的单向绑定
- ng-modle 是 $scope <-> view 的双向绑定
在 AngularJS 中显示模型中的数据有两种方式:
表达式
<p>{{text}}</p>
使用基于属性的指令,ng-bind:
<p ng-bind="text"></p>
主要区别在于,使用花括号语法时,在 AngularJS 使用数据替换模板中的花括号时,第一个加载的页面,通常是应用中的 index.html,其未被渲染的模板可能会被用户看到。而使用第二站方法的视图不会遇到这种问题。
原因是,浏览器需要首先加载 index.html 页面,渲染它,然后 AngularJS 才能把它解析成你期望看到的内容。
在 AngularJS 中,服务是一个函数或对象,可在你的 AngularJS 应用中使用。
- $location 地址服务
- $http
- $timeout 超时器
- $interval 定时器
$http
<script>
var app = angular.module('myApp', []);
app.controller('siteCtrl', function($scope, $http) {
$http.get("https://www.runoob.com/try/angularjs/data/sites.php")
.success(function (response) {$scope.names = response.sites;});
});
</script>
- ng-disabled 禁用
- ng-show 是否显示
- ng-hide 是否隐藏
- ng-click 点击时触发某个事件
- ng-include="'file.html'"
- 隐式注入:不需要开发人员干预,angularJS 自动根据参数的名称识别和注入数据
- 显式注入:开发人员通过字符串描述,告诉 angular 需要注入的对象名称
在之前学习 AngularJS 的过程中,用到了隐式依赖注入,比如:
<script type="text/javascript">
angular.module('app', [])
.controller('Controller1', function($scope) {
$scope.something = 'hello world';
});
</script>
依赖注入 $scope。这么写有个弊端,在发布的时候,往往要压缩 JavaScript 代码,压缩时,会替换掉变量名。比如 $scope 会替换成长度更小的 a,但是 $scope 这个名字又是不能改动的,否则会无法识别。所以这种隐式的依赖注入方法不好。
AngularJS 提倡用以下这种方法:
<script type="text/javascript">
angular.module('app', [])
.controller('Controller1', ['$scope', function(parm){
parm.something = 'hello world';
}]);
</script>
这种方法是显式的依赖注入,把 $scope 当作一个字符串,则压缩时不会被替换掉,随便命名一个参数 parm,在函数体中运用时同名即可。
不仅是 controller,其它需要依赖注入的地方都提倡用显式的方法。
var myApp = angular.module('myApp', [], function () {
})
// 隐式的依赖注入
// .factory('CustomeService', function ($window) {
// console.log($window);
// })
// 显示的依赖注入
.factory('CustomService',['$window',function (a) {//a 参数就是 $window
console.log(a);
}])
// 隐式的依赖注入
.controller('secondController', function ($scope, CustomService) {
})
// // 显式的依赖注入(推荐使用)
// .controller('secondController', ['$scope', '$filter', function (a, b) {
// console.log(b('json')([1, 2, 3, 4, 5]));
// }])
function otherController(a) {
console.log(a);
}
otherController.$inject = ['$scope']; // 此处的 $scope 就是上面的参数 a
MVVM 核心:Model(模型),View(UI),ViewModel(视图模型)
Model:数据展现的对象模型
View:页面 UI
ViewModel:实现 Model 和 View 的双向绑定(ViewModel 的含义就是 "Model of View",视图的模型)
它们的工作模型应该是:Model<=>ViewModel<=>View
数据双向绑定
在 Model 中变量和方法 $scope.variable & $scope.function()
在 View 界面中不会出现 $scope 字符,直接写在 {{expression}},会输出对应的 variable 或者 function() 的值,而表达式中的 variable 和 function() 是 $scope 的属性或者方法
或者百度静态资源库
- angular.min.js
- angular-route.min.js----------- 路由
- angular-resource.min.js-------- 与后端 restful 接口进行交互
例子:project/zabbix_manager_web/urls.py
from django.conf.urls import url,include
from django.contrib import admin
from django.views.generic import TemplateView ##
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('api.urls')),
url(r'^$', TemplateView.as_view(template_name='index.html')),##
]
例子:project/zabbix_manager_web/settings.py
在 settings.py 设置默认搜索 project 目录下的 templates 目录,并在 project 目录下创建 templates 目录
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [BASE_DIR+"/templates"], #*
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
例子:project/templates/index.html
<html>
<body>
meetbill
</body>
</html>
#python manage.py runserver 0.0.0.0:8888
例子:project/zabbix_manager_web/settings.py 末尾添加如下,并在 project 目录下创建 static 目录
STATICFILES_DIRS = ( BASE_DIR + '/static', )
(1) 将 angular 文件下载到 project/static/js/angular/angular.min.js
(2) 编写 controller 文件 project/static/js/angular/controller.js
var app = angular.module("myApp", []);
app.config(
function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
})
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
app.controller("myCtrl", function($scope) {
$scope.name = "wangbin";
});
(3) 编写 html 文件 project/templates/index.html
<html>
<head>
<meta charset="utf-8">
<script src="/static/js/angular/angular.min.js"></script>
<script src="/static/js/angular/controller.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<p>名字 : <input type="text" ng-model="name"></p>
<h1>Hello [[ name ]]</h1>
</div>
</body>
</html>
#python manage.py runserver 0.0.0.0:8888
(1) 编写 html 文件 project/templates/index.html
- 增加 angular-route js 文件
- 增加 ng-view 标签
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="static/mylib/bootstrap/css/bootstrap.min.css">
<script type="text/javascript" src="static/mylib/angular/angular.min.js"></script>
<script type="text/javascript" src="static/mylib/angular/angular-route.min.js"></script>
<script type="text/javascript" src="static/js/controller.js"></script>
<script type="text/javascript" src="static/js/directives.js"></script>
</head>
<body>
<div class="container">
<div ng-view></div>
</div>
<script type="text/javascript" src="static/mylib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="static/mylib/bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
编写 controller 文件 project/static/js/angular/controller.js
var app = angular.module('myApp', ['ngRoute']);
app.controller('RootCtrl', ['$scope', function($scope){
$scope.title = "Home Page";
}]);
app.controller('CatsCtrl', ['$scope', function($scope){
$scope.title = "Cats Page";
}]);
app.config(
function($interpolateProvider) {
$interpolateProvider.startSymbol('[[');
$interpolateProvider.endSymbol(']]');
});
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
}]);
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/main', {
controller : 'RootCtrl',
template : '<h1>xxxxxxxxxxxxxx[[title]]</h1>'
})
.when('/cats', {
controller : 'CatsCtrl',
template : '<h1>kkkkkkkkkkkkkkkkk[[title]]</h1>'
})
.otherwise({
redirectTo : '/main'
});
}]);
#python manage.py runserver 0.0.0.0:8888
浏览器访问 http://IP:8888/#!/main
查看运行效果,同时可以切换至http://IP:8888/#!/cats
查看其他视图
【2018 年 1 月 4 日】
根据 django 的 STATIC_URL 设置进行配置多视图 html
如:
比如我的一个 html 文件的本地地址为 /home/mysite/common_static/partials/main.html
Django 中的设置如:STATIC_URL = '/static/'
浏览器上输入: http://192.168.1.2:8000/static/partials/main.html 那么就相当与访问 /home/mysite/common_static/partials/main.html
故而:在 2.3 的基础上,将 template 修改为 templateUrl 同时配置对应的 html 文件位置即可,即 'static/partials/main.html'
【2018 年 1 月 4 日】
根据 django 的 STATIC_URL 设置进行配置多视图 html
如:
比如我的一个 html 文件的本地地址为 /home/mysite/common_static/partials/main.html
Django 中的设置如:STATIC_URL = '/static/'
浏览器上输入: http://192.168.1.2:8000/static/partials/main.html 那么就相当与访问 /home/mysite/common_static/partials/main.html
故而:在 2.3 的基础上,将 template 修改为 templateUrl 同时配置对应的 html 文件位置即可,即 'static/partials/main.html'
这个指令是导航栏
编写指令文件 project/static/js/angular/directives.js
var directives = angular.module('cloudview.directives', []);
directives.directive('navbar', function(){
return {
restrict: 'A',
transclude: true,
scope: {},
template: '<div class="navbar navbar-inverse navbar-fixed-top">\
<div class="container">\
<a class="navbar-brand" href="#!/main">CloudView</a>\
<div class="navbar-collapse collapse">\
<ul class="nav navbar-nav">\
<li ng-class="{ active:\'main\'== $root.currentItem }"><a href="#!/main">首页</a></li>\
<li ng-class="{ active:\'service\'== $root.currentItem }"><a href="#!/service">服务管理</a></li>\
<li ng-class="{ active:\'utils\'== $root.currentItem }"><a href="#!/utils">系统工具</a></li>\
</ul>\
<ul class="nav navbar-nav navbar-right">\
<li ng-class="{ active:\'setting\'== $root.currentItem }"><a href="#!/setting">设置</a></li>\
<li class="divider-vertical"></li>\
<li ng-class="{ active:\'setting\'== $root.currentItem }"><a href="#!/logout">退出</a></li>\
</ul>\
</div>\
</div>\
</div>',
replace: true
};
});
html 中使用此指令
<div navbar ></div>
导航栏使用 logo
<div class="navbar-header">
<a class="navbar-brand" href="#">
<img alt="Brand" style="max-width:100px;margin-top:-7px;" src="...">
</a>
</div>
解决悬浮层(悬浮 header、footer)会遮挡住内容的方法
导航栏使用 navbar-fixed-top
悬浮在最上层并置顶时,会发现导航栏会遮盖页面上面的部分
可以使用如下方法:(修改 templates/index.html)增加 style="margin-top:50px;"
<body>
<div class="container" style="margin-top:50px;">
<div ng-view></div>
</div>
</body>
50px 为 navbar 的默认高度
通过 controller 中的 $rootScope.currentItem 与 特定菜单进行比较,以确定此菜单状态
tscope 设置的变量在所有 controller 里面都是可以直接用{{$root. 变量名}}来显示的,当然也可以赋值给 $scope.
django 模板默认使用的是{{}},AngularJS 默认也是{{}},两者冲突了,代码里 app.config 将 AngularJS 规则改为 [[]],解决了冲突
ng-app 指令定义一个 AngularJS 应用程序。
ng-model 指令把元素值(比如输入域的值)绑定到应用程序。
ng-bind 指令把应用程序数据绑定到 HTML 视图。
AngularJS 应用组成如下:
- View(视图), 即 HTML。
- Model(模型), 当前视图中可用的数据。
- Controller(控制器), 即 JavaScript 函数,可以添加或修改属性。
scope 是模型。scope 是一个 JavaScript 对象,带有属性和方法,这些属性和方法可以在视图和控制器中使用。
用 routeProvider 将视图分解成布局和模板视图,并且根据用户当前访问的 URL 来展示对应的视图。
从 1.2 版本开始,AngularJS 将 ngRoutes 从核心代码中剥离出来成为独立的模块。我们需要安装并引用它,才能够在 AngularJS 应用中正常地使用路由功能
- angular-route.js。
$routeProvider.when(url,{
template:string, // 在 ng-view 中插入简单的 html 内容
templateUrl:string, // 在 ng-view 中插入 html 模版文件
controller:string,function / array, // 在当前模版上执行的 controller 函数
controllerAs:string, // 为 controller 指定别名
redirectTo:string,function, // 重定向的地址
resolve:object<key,function> // 指定当前 controller 所依赖的其他模块
});
console.log('click');
$log.log('value=='+$scope.mob);
$log.info('value=='+$scope.mob);
$log.warn('value=='+$scope.mob);
$log.error('value=='+$scope.mob);
$log.debug('value=='+$scope.mob);
url = http://qiaole.sinaapp.com?#name=cccccc
$location.absUrl();
// http://qiaole.sinaapp.com?#name=cccccc
$location.host();
// qiaole.sinaapp.com
$location.port();
// 80
$location.protocol();
// http
$location.url();
// ?#name=cccccc
// 获取 url 参数
$location.search().name;
// or
$location.search()['name'];
html
<div ng-app="app">
<div ng-controller="PromiseCtrl">
<h2>$resource().get()</h2>
<h3>Example 1 : The data directly returned by $resource().get()</h3>
<p>{{example1}}</p>
<h3>Example 2 : Success callback with $promise and then()</h3>
<p>{{example2}}</p>
<h3>Example 3 : Error callback with $promise and then()</h3>
<p>{{example3}}</p>
<h3>Example 4 : Success callback inside the get()</h3>
<p>{{example4}}</p>
<h3>Example 5 : Error callback inside the get()</h3>
<p>{{example5}}</p>
</div>
</div>
js
angular.module('app', [ 'ngResource' ]).controller('PromiseCtrl', [ '$scope', '$resource', function($scope, $resource) {
var resource = $resource('/echo/json/:fakeOptionalParameter');
$scope.example1 = resource.get();
resource.get().$promise.then(function(value) {
$scope.example2 = value;
});
resource.get({
fakeOptionalParameter : '/error'
}).$promise.then(null, function(value) {
$scope.example3 = value.status;
});
resource.get(function(value) {
$scope.example4 = value;
});
resource.get({
fakeOptionalParameter : '/error'
}, function(value) {
}, function(httpResponse) {
$scope.example5 = httpResponse.status;
});
} ]);
输出
$resource().get()
Example 1 : The data directly returned by $resource().get()
{}
Example 2 : Success callback with $promise and then()
{}
Example 3 : Error callback with $promise and then()
404
Example 4 : Success callback inside the get()
{}
Example 5 : Error callback inside the get()
404
bootstrap 的标签页切换可以通过以下链接进行查看
https://github.com/meetbill/pine/wiki/bootstrap_learn
bootstrap 的标签页:
- 优点:编写简单
- 缺点:无法通过特定 url 在页面上展示对应的 tab 页面
controller.js 的对应 controller 中增加如下信息,其中
- location.search() 可以获取到 url 参数信息
$scope.sec = $location.search().sec
if ($scope.sec == null) {
$scope.sec = 'config'
$location.search("sec","config")
}
$scope.change_sec=function (sec) {
$location.search("sec",sec)
};
console.log($scope.sec);
标签页处代码如下,这样就可以根据获取到的参数信息默认高亮某个 tab,以及进行点击切换时进行更新 URL 参数
<ul class="nav nav-tabs">
<li ng-class="{active: sec == 'config'}" ><a ng-click="change_sec('config')" data-toggle="tab" data-target="#config">配置检查</a></li>
<li ng-class="{active: sec == 'status'}" ><a ng-click="change_sec('status')" data-toggle="tab" data-target="#status">运行状态</a></li>
</ul>
标签对应的内容如下:
<div class="tab-content">
<div class="tab-pane" ng-class="{active: sec == 'config'}" id="config">
<h4>配置检查</h4>
</div>
<div class="tab-pane" ng-class="{active: sec == 'status'}" id="status">
<h4>运行状态</h4>
</div>
</div>
<!DOCTYPE html>
<html lang="en" ng-app="myapp">
<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>Document</title>
<script src="https://cdn.bootcss.com/angular.js/1.6.4/angular.min.js"></script>
</head>
<body>
<table ng-controller="repeatController" border="1">
<thead>
<td>年级</td>
<td>姓名</td>
<td>年龄</td>
</thead>
<tbody>
<tr ng-repeat-start="group in list">
<td rowspan="{{group.item.length}}">{{group.nian}}</td>
<td>{{group.item[0].name}}</td>
<td>{{group.item[0].age}}</td>
</tr>
<tr ng-repeat-end ng-repeat="single in group.item" ng-hide="$first">
<td>{{single.name}}</td>
<td>{{single.age}}</td>
</tr>
</tbody>
</table>
<script>
var data = [
{
"nian": "一年级",
"item": [
{
"name": "张三",
"age": "23"
},
{
"name": "张三",
"age": "23"
}
]
},
{
"nian": "二年级",
"item": [
{
"name": "张三",
"age": "23"
},
{
"name": "张三",
"age": "23"
}
]
},
{
"nian": "三年级",
"item": [
{
"name": "张三",
"age": "23"
},
{
"name": "张三",
"age": "23"
}
]
}
];
repeatController = function ($scope){
$scope.list = data;
}
repeatController.$inject = ['$scope'];
angular.module('myapp',[]).controller('repeatController',repeatController);
</script>
</body>
</html>
其中 $first
是去掉循环中的第一个元素,因为上面已经有了第一个元素了,不设置此项将会排版错误和第一个元素显示两行
AngularJS 使用 ng-src 替换了 src
<img ng-src="{{imageUrl}}">
错误写法
<img src="http://www.coderlady.com/avatar/{{hash}}"/>
正确写法
<img ng-src="http://www.coderlady.com/avatar/{{hash}}"/>
这是因为在加载页面的时候,在 Angular 加载完成之前,浏览器会试图从 http://www.coderlady.com/avatar/{{hash}} 加载图片,当然这会失败. 一旦 Angular 加载完成以后,浏览器就会明白{{hash}}变量需要被具体值代替,比如 logo.png. 然后就会到正确的 http://www.coderlady.com/avatar/logo.png 去加载图片。这显然就要执行两次操作。
ng-src 就解决了这个问题,因为它会等 Angular 加载完成以后,才会到正确的地址去加载数据。
PS:butterfly-fe 的右上角用户头像,就可以使用 ng-src 进行获取头像
angularjs 1.2 和 1.3controller 写法不一样
1.2 controller 可以写成 function OrderListCtrl($scope){
$scope.xxx=ooo;
}
1.3 要这样写 ngApp.controller(“OrderListCrl”,function($scope){
$scope.xxx=ooo;
});
在 html 展示的时候
"(key,value) in dict" 即可输出 key
"xxx in dict" 时,xxx 默认是 value
- [$injector:unpr] 注入错误
- [$injector:modulerr] 模块注入错误