• Posts tagged "angularjs"

Blog Archives

AngularJS去掉的URL里的#号

AngularJS体验式编程系列文章,将介绍如何用angularjs构建一个强大的web前端系统。angularjs是由Google团队开发的一款非常优秀web前端框架。在当前如此多的web框架下,angularjs能脱颖而出,从架构设计上就高人一等,双向数据绑定,依赖注入,指令,MVC,模板。Angular.js创新地把后台技术融入前端开发,扫去jQuery一度的光芒。用angularjs就像写后台代码,更规范,更结构化,更可控。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/angularjs-url/

angularjs-url

前言

天天都在用AngularJS,各类文档也都看过好几遍,但总是些编程上的事找不到优雅的解决办法。今天终于把AngularJS的项目访问路径URL里的#号去掉了,这个问题不见得有多难,关键是花多长时间去理解AngularJS框架本身。

目录

  1. URL的#号问题
  2. 找到错误原因
  3. 静态网站的解决方案
  4. 动态网站的解决方案

1. URL的#号问题

使用AngularJS的朋友都应该了解,AngularJS框架定义了自己的前端路由控制器,通过不同URL实现单面(ng-app)对视图(ng-view)的部署刷新,并支持HTML5的历史记录功能,详细介绍可以参考文章:AngularJS路由和模板

对于默认的情况,是不启动HTML5模式的,URL中会包括一个#号,用来区别是AngularJS管理的路径还是WebServer管理的路径。

比如:下面的带#号的URL,是AngularJS管理的路径。

  • http://onbook.me/
  • http://onbook.me/#/
  • http://onbook.me/#/book
  • http://onbook.me/#/about

这种体验其实是不太友好的,特别是像我这种喜欢简洁设计的人,#号的出现非我自愿的,怎么看怎么难受。AngularJS框架提供了一种HTML5模式的路由,可以直接去掉#号。

通过设置$locationProvider.html5Mode(true)就行了。


book.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {

   //..省略代码
    $locationProvider.html5Mode(true);
}]);

支持HTML5的路由URL。

  • http://onbook.me/
  • http://onbook.me/book
  • http://onbook.me/about

接下来的问题就来了,当用这种方式设置了路径以后。如果用户从首页(http://onbook.me/)开始访问,然后跳转到 图书页(http://onbook.me/book)一切正常。但如果用户直接打开 图书页(http://onbook.me/book) ,就会出现404错误。

url1

就是这个问题纠结了我好长时间,让我不得不用带#号的URL。

2. 找到错误原因

那么,这个问题的原因出在哪里了呢? 在路径解析上出错了。

让我从头说起,AngularJS是单页应用,一个ng-app对应一个页面,一个URL。AngularJS实现了自己的前端路由,让一个ng-app可以管理多个URL,再对应到多个ng-vew上面。当我们去访问URL(http://onbook.me/book) 的时候,怎么确定这个路径是 WebServer 后台管理的URL还是AngularJS前台管理的URL呢?

分2种情况看:

  • 1. 用户如果是先访问 首页(http://onbook.me),然后再跳转到 页面(http://onbook.me/book),则这个跳转是由AngularJS前台管理的URL,访问是正常的。
  • 2. 用户直接访问 页面(http://onbook.me/book)时,请求是先被提交到了WebServer后台,后台路由没有对应页面(http://onbook.me/book)的路由管理,就会出现404的错误。

如果能把这层想明白,技术上就非常容易解决了。我们让WebServer把属于AngularJS管理的路由URL,都发转到ng-app就可以解决404的问题了,同时,没有#号,还支持HTML5的历史记录查询!!

实现起来分为2种解决方案:

  • 1. 静态网站:纯前台网站(JS+HTML+CSS),通过Nginx提供Web服务。
  • 2. 动态网站:前台(JS + HTML + CSS) + 后台Node.js提供Web服务。

3. 静态网站的解决方案

静态网站,我们需要修改的地方包括3个文件

  • index.html : ng-app的定义文件
  • app.js : 对应ng-app的控制文件
  • nginx.conf : nginx的网站配置文件

编辑 index.html,增加base标签。


<html lang="zh-CN" ng-app="book">
<head>
    <base href="/">
	
// 省略代码
</head>

编辑app.js,增加 $locationProvider.html5Mode(true);


book.config(['$routeProvider', '$locationProvider', '$sceProvider', 'tplProvider', function ($routeProvider, $locationProvider, $sceProvider, tplProvider) {
    $routeProvider
        .when('/', {templateUrl: tplProvider.html('welcome'), controller: 'WelcomeCtrl'})
        .when('/book', {templateUrl: tplProvider.html('book'), controller: 'BookCtrl'})             //图书
        .when('/book-r1', {templateUrl: tplProvider.html('book-r1'), controller: 'BookR1Ctrl'})   //R的极客理想
        .when('/video', {templateUrl: tplProvider.html('video'), controller: 'VideoCtrl'})         //视频
        .when('/about', {templateUrl: tplProvider.html('about'), controller: 'AboutCtrl'})         //关于作者
        .otherwise({redirectTo: '/'});
    $locationProvider.html5Mode(true);
}]);

编辑nginx的配置文件,增加try_files配置。


server {
        set $htdocs /www/deploy/mysite/onbook;
        listen 80;
        server_name onbook.me;
        location / {
            root $htdocs;
            try_files $uri $uri/ /index.html =404;
        }
}

这样,静态网站就搞定了,没有麻烦的#号了,可以直接访问和任意页面的刷新。

4. 动态网站的解决方案

动态网站,我们同样需要修改的地方包括3个文件。

  • index.html : ng-app的定义文件
  • app.js : 对应ng-app的控制文件
  • server.js : Express框架的路由访问控制文件

index.html 和 app.js两个文件修改,同静态网站的解决方案。动态网站,一般不是通过Nginx直接路由,而是通过Web服务器管理路由。假设我们使用的是Node.js的Express的Web框架。

打开Express框架的路由访问控制文件server.js,增加路由配置。


app.use(function (req, res) {
    console.log(req.path);
    if(req.path.indexOf('/api')>=0){
        res.send("server text");

    }else{ //angular启动页
        res.sendfile('app/index.html');
    }
});

设置当 站内路径(req.path) 不包括 /api 时,都转发到 AngularJS的ng-app(index.html)。所以,我们再直接访问地址 (http://onbook.me/book)时,/book 不包括 /api,就会被直接转发到AngularJS进行路由管理。我们就实现了路由的优化!

我已用了AngularJS有8-9个月了,主要功能都用到了,但还不见其全貌。经常会遇到各种问题,不过比起jQuery的各种无解的问题,还是值得的。优秀的框架值得我们的研究和使用,在摸索中前进!

转载请注明出处:
http://blog.fens.me/angularjs-url/

打赏作者

Bootstrap3多级导航菜单

AngularJS体验式编程系列文章,将介绍如何用angularjs构建一个强大的web前端系统。angularjs是由Google团队开发的一款非常优秀web前端框架。在当前如此多的web框架下,angularjs能脱颖而出,从架构设计上就高人一等,双向数据绑定,依赖注入,指令,MVC,模板。Angular.js创新地把后台技术融入前端开发,扫去jQuery一度的光芒。用angularjs就像写后台代码,更规范,更结构化,更可控。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/bootstrap-multilevel-navbar/

bootstrap3-navbar

前言

在上一篇文章中Angular结合Bootstrap3的导航菜单,我们看到直接用Bootstrap3的默认导航菜单只支持到二级的菜单,如果想做成多级导航菜单,那又要自己动手了。

本文将介绍如何实现多限级导航菜单。

目录

  1. 静态多级菜单实现
  2. 动态多级菜单实现

1. 静态多级菜单实现

要实现多级菜单,我们要分两步走,第一步就是把静态菜单的功能实现,通过纯静态的HTML代码完成。第二步,通过Angluarjs进行动态实现,最后把数据和程序分离,通过Ajax加载多级菜单数据。

我们先从静态多级菜单开始动手,一个六级导航菜单是什么样子呢?

m-nav1

如上图所示,我们定义一些功能需求。

  • 1级菜单是导航条上的文字。
  • 当1级菜单导航事件被触发,显示2级菜单导航,在1级菜单的正下方显示。
  • 当2级菜单导航事件被触发,显示3级菜单导航,在2级菜单的右方显示。
  • 当3级菜单导航事件被触发,显示4级菜单导航,在3级菜单的右方显示。
  • 以此类推,不考虑下级菜单显示出界问题。

继续上文中的项目环境,增加一个新HTML文件: page3.html


~ vi D:\workspace\javascript\angular-navbar\page3.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>多级导航菜单</title>
    <meta name="description" content="多级导航菜单">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="fragment" content="!" />

    <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="/css/main.css">
</head>
<body ng-app="page2">

<div class="container">
    <div class="row" ng-controller="NavbarCtrl">
        <nav class="navbar navbar-default" role="navigation">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">多级菜单导航</a>
            </div>

            <div class="collapse navbar-collapse navbar-ex1-collapse">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Link</a></li>
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Multi Level <b class="caret"></b></a>
                        <ul class="dropdown-menu menu-top">
                            <li><a href="#">Level 1</a></li>
                            <li class="dropdown-submenu"> <a tabindex="-1" href="#">More options</a>
                                <ul class="dropdown-menu">
                                    <li><a tabindex="-1" href="#">Level 2</a>
                                    </li>
                                    <li class="dropdown-submenu"> <a href="#">More..</a>
                                        <ul class="dropdown-menu">
                                            <li><a href="#">Level 3</a>
                                            </li>
                                            <li><a href="#">Level 3</a>
                                            </li>
                                            <li class="dropdown-submenu"> <a href="#">More..</a>
                                                <ul class="dropdown-menu">
                                                    <li><a href="#">Level 4</a>
                                                    </li>
                                                    <li><a href="#">Level 4</a>
                                                    </li>
                                                    <li class="dropdown-submenu"> <a href="#">More..</a>
                                                        <ul class="dropdown-menu">
                                                            <li><a href="#">Level 5</a>
                                                            </li>
                                                            <li><a href="#">Level 5</a>
                                                            </li>
                                                        </ul>
                                                    </li>

                                                </ul>
                                            </li>

                                        </ul>
                                    </li>
                                    <li><a href="#">Level 2</a>
                                    </li>
                                    <li><a href="#">Level 2</a>
                                    </li>
                                </ul>
                            </li>
                            <li><a href="#">Level 1</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </nav>
    </div>
</div>

<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>

<script src="/js/app.js"></script>

</body>
</html>

新建一个css文件:main.css


~ vi D:\workspace\javascript\angular-navbar\css\main.css

.dropdown:hover .menu-top {
    display: block;
}

.dropdown-submenu{
    position:relative;
}

.dropdown-submenu > .dropdown-menu{
    top:0;
    left:100%;
    margin-top:-6px;
    margin-left:-1px;
    -webkit-border-radius:0 6px 6px 6px;
    -moz-border-radius:0 6px 6px 6px;
    border-radius:0 6px 6px 6px;
}

.dropdown-submenu:hover > .dropdown-menu{
    display:block;
}

.dropdown-submenu > a:after{
    display:block;
    content:" ";
    float:right;
    width:0;
    height:0;
    border-color:transparent;
    border-style:solid;
    border-width:5px 0 5px 5px;
    border-left-color:#cccccc;
    margin-top:5px;
    margin-right:-10px;
}

.dropdown-submenu:hover > a:after{
    border-left-color:#ffffff;
}

.dropdown-submenu .pull-left{
    float:none;
}

.dropdown-submenu.pull-left > .dropdown-menu{
    left:-100%;
    margin-left:10px;
    -webkit-border-radius:6px 0 6px 6px;
    -moz-border-radius:6px 0 6px 6px;
    border-radius:6px 0 6px 6px;
}

刷新一下网页,我们能就看到上面的截图的效果,代码参考:http://firdaus.grandexa.com/2013/09/twitter-bootstrap-3-multilevel-dropdown-menu/

通过HTML和CSS就实现了多级菜单的静态展示效果,如果导航菜单不是经常变化,那么用静态的方式,把代码写死就可以了。但有一些场景,菜单是需要动态生成,比如通过权限控制访问链接,每个用户的权限不一样,那么能看到的菜单选项也就不一样,这个时候就需要做成动态的,用程序去控制菜单的加载和展示。

2. 动态多级菜单实现

有了静态多级导航菜单的HTML代码结构,改写成动态的,其实也不太复杂。

我们需要做2件事:

  • 把导航菜单的数据结构化存储,比如 存放到文件 nav.json。
  • 用Angularjs的API加载nav.json数据,进行展示。

我们先定义一下导航菜单的数据格式,以JSON格式定义,每个菜单项都有3个属性字段

  • label: 导航菜单项显示的名字。
  • link: 导航菜单项的跳转链接,可以不定义。
  • children: 导航菜单项的子菜单,循环对象存储。

{
    "label": "levelA",
    "link": "#",
    "children": [
        {
            "label": "levelB",
            "link": "#",
            "children": []
        }
    ]
}

下面我们用真实的数据定义导航菜单,以我的金融系统为例。

m-nav3

新建JSON数据文件:nav.json。


~ vi D:\workspace\javascript\angular-navbar\js\nav.json

[
    {
        "label": "债券",
        "children": [
            {
                "label": "可转债",
                "children": [
                    {"label": "可转债溢价率分析","link":"#"},
                    {"label": "可转债NS定价","link":"#"},
                    {"label": "可转债归因分析","link":"#"},
                    {"label": "可转债套利实时监控","link":"#"}
                ]
            },
            {
                "label": "信用债",
                "children": [
                    {"label": "交易所债券监控","link":"#"}
                ]
            },
            {
                "label": "利率债","link":"#",
                "children": []
            },
            {
                "label": "国债期货",
                "children": [
                    {"label": "国债期货表现分析","link":"#"},
                    {"label": "国债期货实时套利监控","link":"#"},
                    {"label": "IRR历史时间序列查询","link":"#"},
                    {"label": "IRR实时监控","link":"#"}
                ]
            }
        ]
    },
    {
        "label": "股票",
        "children": [
            {
                "label": "基本面分析",
                "children": [
                    {"label": "上市公司基本面数据查看","link":"#"}
                ]
            },
            {
                "label": "量化选股策略",
                "children": []
            }
        ]
    },
    {
        "label": "宏观",
        "children": [
            {
                "label": "宏观数据",
                "children": [
                    {"label": "宏观数据概览","link":"#"}
                ]
            },
            {
                "label": "宏观经济预测",
                "children": []
            },
            {
                "label": "宏观经济和大类资产表现",
                "children": []
            }
        ]
    }
]

我们看到这个导航菜单的数据,有3级,“债券–>可转债–>可转债归因分析”,那么接下我们就直接实现对三级菜单的编程。创建HTML文件page4.html。


~ vi D:\workspace\javascript\angular-navbar\page4.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>多级动态导航菜单</title>
    <meta name="description" content="多级动态导航菜单">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="fragment" content="!" />

    <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
    <link rel="stylesheet" href="/css/main.css">
</head>
<body ng-app="page4">

<div class="container">
    <div class="row" ng-controller="NavbarCtrl">
        <nav class="navbar navbar-default" role="navigation">
            <div class="navbar-header">
                <a class="navbar-brand" href="/">量化投资平台</a>
            </div>

            <div class="collapse navbar-collapse navbar-ex1-collapse">
                <ul class="nav navbar-nav">
                    <li ng-repeat="a1 in navbar" class="dropdown">
                        <a href="?{{ a1.label }}" class="dropdown-toggle" data-toggle="dropdown">{{ a1.label }} <b class="caret"></b></a>
                        <ul class="dropdown-menu menu-top">
                            <li ng-repeat="a2 in a1.children" class="dropdown-submenu">
                                <a tabindex="-1" href="?{{ a2.label }}">{{ a2.label }}</a>
                                <ul ng-show="a2.children.length>0" class="dropdown-menu">
                                    <li ng-repeat="a3 in a2.children">
                                        <a href="?{{ a3.label }}" ng-click="go(a3.link)">{{ a3.label }}</a>
                                    </li>
                                </ul>
                            </li>
                        </ul>
                    </li>
                </ul>
            </div>
        </nav>
    </div>
</div>

<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>

<script src="/js/app.js"></script>

</body>
</html>

在Angularjs的控制器文件app.js文件中,增加page4的定义。


var page4 = angular.module('page4', ['ui.bootstrap', 'ngRoute']);

page4.config(['$routeProvider', '$locationProvider', '$sceProvider', function ($routeProvider, $locationProvider, $sceProvider) {
    $routeProvider
        .when('/', {controller: 'DemoCtrl'})
        .otherwise({redirectTo: '/'});
    $locationProvider.html5Mode(true);
}]);

page4.controller('NavbarCtrl', function ($scope,$http,$location) {
    $http.get("/js/nav.json").success(function(json){
        $scope.navbar = json;
    });
});

page4.controller('DemoCtrl', function () {
    // nothing
});

查看一下显示效果,与上面的截图类似。

m-nav4

文章到这里就结束了,已经实现了我的功能需求。但这个话题还有很多可以优化的地方,比如实现无限级的导航菜单,菜单的展示样式替换,展示区间的控制,鼠标动作事件,封装成Angularjs的插件开源项目等。有兴趣的同学,可以我的程序的基础上继续努力,做出优秀的开源项目来。

代码已上传到github:https://github.com/bsspirit/angular-navbar,同学可以根据需要自行下载,也可以直接通过命令下载代码。


git clone https://github.com/bsspirit/angular-navbar.git
cd angular-navbar
bower install
anywhere

转载请注明出处:
http://blog.fens.me/bootstrap-multilevel-navbar/

打赏作者

Angular+Bootstrap3导航菜单

AngularJS体验式编程系列文章,将介绍如何用angularjs构建一个强大的web前端系统。angularjs是由Google团队开发的一款非常优秀web前端框架。在当前如此多的web框架下,angularjs能脱颖而出,从架构设计上就高人一等,双向数据绑定,依赖注入,指令,MVC,模板。Angular.js创新地把后台技术融入前端开发,扫去jQuery一度的光芒。用angularjs就像写后台代码,更规范,更结构化,更可控。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/bootstrap-angularjs-navbar/

angularjs-bootstart-navbar

前言

导航菜单是一个网站中必备的一个组件,不仅能给用户提供方便的网站浏览指引,还能为SEO提供良好爬取路径。基于AngularJS+Bootstrap3的网站越来越流行,应该怎么实现导航菜单呢?看本文的介绍。

目录

  1. Bootstrap3中的导航菜单
  2. AngularJS中的导航菜单 – 点击事件
  3. AngularJS中的导航菜单 – 路过事件

1. Bootstrap3中的导航菜单

Bootstrap3的文档中我们可以看到,默认提供的导航菜单支持下拉功能,单击触发,支持2级菜单,如下图所示。

bootstrap-nav

实现文档中的效果,我们可以快速创建一个静态的HTML的项目,创建细节不多解释,参考文章: 快速搭建Web环境 Angularjs + Express3 + Bootstrap3bower解决js的依赖管理

创建项目目录


~ mkdir D:\workspace\javascript\angular-navbar\
~ cd D:\workspace\javascript\angular-navbar\

创建依赖配置文件bower.json


~ vi D:\workspace\javascript\angular-navbar\bower.json

{
    "name": "angular-navbar",
    "version": "0.0.1",
    "author": "Conan Zhang",
    "dependencies": {
    }
}

下载依赖包


~ D:\workspace\javascript\angular-navbar>bower install bootstrap --save
bower bootstrap#*               cached git://github.com/twbs/bootstrap.git#3.1.1
bower bootstrap#*             validate 3.1.1 against git://github.com/twbs/bootstrap.git#*
bower jquery#>= 1.9.0           cached git://github.com/jquery/jquery.git#2.1.1
bower jquery#>= 1.9.0         validate 2.1.1 against git://github.com/jquery/jquery.git#>= 1.9.0
bower bootstrap#~3.1.1         install bootstrap#3.1.1
bower jquery#>= 1.9.0          install jquery#2.1.1
bower                          no-json No bower.json file to save to, use bower init to create one
bootstrap#3.1.1 bower_components\bootstrap
└── jquery#2.1.1

创建HTML文件:page1.html


~ vi D:\workspace\javascript\angular-navbar\page1.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>Bootstrap导航菜单</title>
    <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>

<div class="container">
    <div class="row">
        <nav class="navbar navbar-default" role="navigation">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">Brand</a>
            </div>

            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li class="active"><a href="#">Link</a></li>
                    <li><a href="#">Link</a></li>
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li class="divider"></li>
                            <li><a href="#">One more separated link</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </nav>
    </div>
</div>

<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>

</body>
</html>

项目目录结构:
project

启动静态服务器,并查看page1.html的预览效果。


~ D:\workspace\javascript\angular-navbar>anywhere
Running at http://192.168.1.12:8000

nav2

第一步我们就现实了Bootstrap3的导航菜单。

2. AngularJS中的导航菜单 – 点击事件

接下来,我们把项目改造成AngularJS的项目,并让Bootstrap配合Angularjs一起使用,实现导航菜单的效果,并对菜单点击事件进行处理,通过切换选中菜单样式。

增加Angularjs的依赖包


~ D:\workspace\javascript\angular-navbar>bower install angular --save
~ D:\workspace\javascript\angular-navbar>bower install angular-route --save
~ D:\workspace\javascript\angular-navbar>bower install angular-bootstrap --save

新建HTML文件Page2.html,通过ng-class,来设置导航菜单的选中样式。


~ vi D:\workspace\javascript\angular-navbar\page2.html

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <title>Bootstrap导航菜单</title>
    <meta name="description" content="Bootstrap导航菜单">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="fragment" content="!" />

    <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
</head>
<body ng-app="page2">

<div class="container">
    <div class="row" ng-controller="NavbarCtrl">
        <nav class="navbar navbar-default" role="navigation">
            <div class="navbar-header">
                <a class="navbar-brand" href="/">Brand</a>
            </div>

            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav">
                    <li ng-class="{active:isActive('/abc')}"><a href="/abc">ABC</a></li>
                    <li ng-class="{active:isActive('/123')}"><a href="/123">123</a></li>
                    <li ng-class="{active:isActive('/dropdown')}" class="dropdown">
                        <a href="/dropdown" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                            <li><a href="/dropdown/label1">label1</a></li>
                            <li><a href="/dropdown/label2">label2</a></li>
                            <li><a href="/dropdown/label3">label3</a></li>
                            <li class="divider"></li>
                            <li><a href="/dropdown/label4">label4</a></li>
                            <li class="divider"></li>
                            <li><a href="/dropdown/label5">label5</a></li>
                        </ul>
                    </li>
                </ul>
            </div>
        </nav>
    </div>
</div>

<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>

<script src="/js/app.js"></script>

</body>
</html>

新建Angularjs文件控制app.js


~ vi D:\workspace\javascript\angular-navbar\js\page2.html

'use strict';

var page2 = angular.module('page2', ['ui.bootstrap', 'ngRoute']);

page2.config(['$routeProvider', '$locationProvider', '$sceProvider', function ($routeProvider, $locationProvider, $sceProvider) {
    $routeProvider
        .when('/', {controller: 'DemoCtrl'})
        .when('/abc', {controller: 'DemoCtrl'})
        .when('/123', {controller: 'DemoCtrl'})
        .otherwise({redirectTo: '/'});
    $locationProvider.html5Mode(true);
}]);

page2.controller('NavbarCtrl', function ($scope, $location) {
    $scope.isActive = function (route) {
        if ($location.path().indexOf('/dropdown') == 0) {
            return  route === '/dropdown';
        }
        return route === $location.path();
    }
});

page2.controller('DemoCtrl', function () {
    // nothing
});

查看运行效果,这样就可以实现菜单选中的效果了!
nav3

3. 导航菜单的鼠标路过事件

使用AngularJS框架后,导航菜单就实现了动态的特性,通过点击实现样式的切换。Dropdown的控件需要鼠标点击,才会下拉出二级菜单,如果用鼠标路过事件就触发可能会更方便,那么下面继续对下拉列表控件改造。

实现方式有好几种,比如通过jQuery增加对鼠标路过事件的监听,或者开发一个AngularJS的插件。不过,还有一种更简单的实现方式,就是通过css来控制。

我们增加一段css代码。


.dropdown:hover .dropdown-menu {
    display: block;
}

简简单单一行定义就完成了,再看看效果。当鼠标路过Dropdown时,下拉菜单就自动弹出了。

nav4

代码已上传到github:https://github.com/bsspirit/angular-navbar,同学可以根据需要自行下载,也可以直接通过命令下载代码。


git clone https://github.com/bsspirit/angular-navbar.git
cd angular-navbar
bower install
anywhere

本文介绍了导航菜单在Angularjs和Bootstrap3的结合使用,这只是第一步,下一篇文章将介绍Bootstrap3多级导航菜单

转载请注明出处:
http://blog.fens.me/bootstrap-angularjs-navbar/

打赏作者

快速搭建Web环境 Angularjs + Express3 + Bootstrap3

AngularJS体验式编程系列文章,将介绍如何用angularjs构建一个强大的web前端系统。angularjs是由Google团队开发的一款非常优秀web前端框架。在当前如此多的web框架下,angularjs能脱颖而出,从架构设计上就高人一等,双向数据绑定,依赖注入,指令,MVC,模板。Angular.js创新地把后台技术融入前端开发,扫去jQuery一度的光芒。用angularjs就像写后台代码,更规范,更结构化,更可控。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/angularjs-express3-bootstrap3/

angular-basic

前言

Angularjs越用越顺手,不仅代码量比jQuery少很多,而且实现思路特别清晰,构建大型的Web前端项目,真是最适合不过了。

Bootstrap让界面美观大方,就连像我这种不懂UE的人,也能做出专业级的水准。再结合Nodejs的Express做后端,三剑合并,太无敌了,大有统一前端开发的趋势,前途不可估量!

目录

  1. 从零开始手工创建Express3项目
  2. 新建Angularjs目录及文件
  3. 配置bower
  4. 配置Angularjs项目
  5. 增加Bootstrap
  6. 完整的项目

1. 从零开始手工创建Express3项目

系统环境:

  • Win7 64bit 旗舰版
  • node v0.10.5
  • npm 1.2.19
  • bower 1.1.2

本文截图中使用的开发工具是WebStorm,请参考文章:AngularJS最理想开发工具WebStorm

创建express项目


~ D:\workspace\javascript>express -e angular-basic
~ D:\workspace\javascript>cd angular-basic && npm install

生成的express项目目录

express

修改app.js的配置

  • 修改ejs: 文件扩展名ejs为html
  • 设置angular: 启动路径为”/”
  • 设置angular: 启动文件为app/index.html

~ vi app.js

var express = require('express')
    , path = require('path')
    , ejs = require('ejs')
    , app = express()
    , server = require('http').createServer(app);

app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.engine('.html', ejs.__express);
app.set('view engine', 'html'); //替换文件扩展名ejs为html
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'app')));

if (app.get('env') === 'development') {
    app.use(express.errorHandler());
}

// angular启动页
app.get('/', function (req, res) {
    res.sendfile('app/index.html');
});

server.listen(app.get('port'), function () {
    console.log('Express server listening on port ' + app.get('port'));
});

如何单独创建Express3的项目,请参考文章:Nodejs开发框架Express3.0开发手记–从零开始

2. 新建Angularjs目录及文件

创建Angularjs需要的目录及文件


D:\workspace\javascript\angular-basic>mkdir app
D:\workspace\javascript\angular-basic>mkdir app\scripts
D:\workspace\javascript\angular-basic>mkdir app\scripts\angular
D:\workspace\javascript\angular-basic>mkdir app\styles
D:\workspace\javascript\angular-basic>mkdir app\views
D:\workspace\javascript\angular-basic>mkdir app\views\component
D:\workspace\javascript\angular-basic>mkdir app\views\tpl

D:\workspace\javascript\angular-basic>touch app\index.html
D:\workspace\javascript\angular-basic>touch app\scripts\angular\app.js
D:\workspace\javascript\angular-basic>touch app\scripts\angular\controllers.js
D:\workspace\javascript\angular-basic>touch app\styles\main.css
D:\workspace\javascript\angular-basic>touch app\views\tpl\welcome.html

D:\workspace\javascript\angular-basic>echo "aaaa" > app\index.html

创建的Angularjs目录及文件

angular

目录解释:

  • app目录: Angular项目的根目录
  • scripts目录: 存放Javascript脚本目录
  • scripts\angular目录: 存放Angular Javascript脚本目录
  • styles目录: 存放css的目录
  • views目录: 存放html的目录
  • views\component目录: 存放html的自定义组件目录
  • views\tpl目录: 存放html的目录

文件解释:

  • app\index.html: Angular项目的入口文件
  • styles\main.css: Angular项目的css文件
  • scripts\angular\app.js: Angular项目全局配置文件
  • scripts\angular\controllers.js: Angular项目全局控制器文件/li>
  • views\tpl\welcome.html: 欢迎页

删除不需要的文件目录


D:\workspace\javascript\angular-basic>rm -rf public
D:\workspace\javascript\angular-basic>rm -rf routes

启动node服务器,检查入口页的配置


D:\workspace\javascript\angular-basic>node app.js
Express server listening on port 3000
GET / 200 11ms - 9b

indexpage

界面显示”aaaa”,说明node启动express,已经指向到app\index.html的页面。

3. 配置bower

接下来,我要通过bower来安装Angularjs和Bootstrap,以及其他依赖的前端库。关于bower的详细使用,请参考文章:bower解决js的依赖管理

新建文件:

    • .bowerrc: bower的环境设置,用于指定bower的依赖库的存放位置
    • bower.json: bower的依赖管理

新建文件: .bowerrc


~ vi .bowerrc

{
    "directory": "app/bower_components"
}

新建文件: bower.json


~ vi bower.json

{
    "name": "angular-basic",
    "version": "0.0.1",
    "dependencies": {
        "angular": "~1.2.12-build.2226",
        "angular-route": "~1.2.12-build.2226"
    },
    "devDependencies": {
    }
}

运行bower,下载Angular依赖库


D:\workspace\javascript\angular-basic>bower install
bower angular-route#~1.2.12-build.2226           cached git://github.com/angular/bower-angular-route.git#1.2.13-build.2242
bower angular-route#~1.2.12-build.2226         validate 1.2.13-build.2242 against git://github.com/angular/bower-angular-route.git#~1.2.12-build.2226
bower angular#~1.2.12-build.2226                 cached git://github.com/angular/bower-angular.git#1.2.13-build.2242
bower angular#~1.2.12-build.2226               validate 1.2.13-build.2242 against git://github.com/angular/bower-angular.git#~1.2.12-build.2226
bower angular#1.2.13-build.2242+sha.e645f7c      cached git://github.com/angular/bower-angular.git#1.2.13-build.2242
bower angular#1.2.13-build.2242+sha.e645f7c    validate 1.2.13-build.2242 against git://github.com/angular/bower-angular.git#1.2.13-build.2242+sha.e645f7c
bower angular-route#~1.2.12-build.2226          install angular-route#1.2.13-build.2242
bower angular#~1.2.12-build.2226                install angular#1.2.13-build.2242

angular-route#1.2.13-build.2242 app\bower_components\angular-route
└── angular#1.2.13-build.2242

angular#1.2.13-build.2242 app\bower_components\angular

下载最新版本的angular和angular-route,类库存放在app/bower_components目录下面。

bower-angular

4. 配置Angularjs项目

  • 修改index.html: 在入口文件,页面模板
  • 修改welcome.html: 欢迎页
  • 修改app.js: 全局配置
  • 修改controller.js: 控制器

修改index.html


<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>Angular-basic</title>
<meta name="description" content="Copyright http://blog.fens.me">
<link rel="stylesheet" href="styles/main.css">
</head>
<body ng-app="app">

<ul>
<li><a href="http://blog.fens.me/angularjs-express3-bootstrap3/">快速搭建Web环境 Angularjs + Express3 + Bootstrap3</a></li>
<li>http://blog.fens.me/angularjs-express3-bootstrap3</li>
</ul>

<div ng-view></div>

<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="scripts/angular/app.js"></script>
<script src="scripts/angular/controllers.js"></script>

</body>
</html>

修改welcome.html


Welcome {{ username }}

修改app.js


'use strict';

var app = angular.module('app', ['ngRoute']);

app.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
    $routeProvider
        .when('/', {templateUrl: '/views/tpl/welcome.html', controller: 'WelcomeCtrl'})
        .otherwise({redirectTo: '/'});
    $locationProvider.html5Mode(true);
}]);

修改controller.js


'use strict';

function WelcomeCtrl($scope){
    $scope.username = 'Conan_Z';
}

重新启动node,查看Angular项目。


D:\workspace\javascript\angular-basic>node app.js
Express server listening on port 3000
GET / 304 8ms
GET /styles/main.css 304 3ms
GET /scripts/angular/app.js 304 6ms
GET /scripts/angular/controllers.js 304 11ms
GET /bower_components/angular-route/angular-route.min.js 200 18ms - 3.82kb
GET /bower_components/angular/angular.min.js 200 19ms - 98.03kb
GET /views/tpl/welcome.html 304 9ms
GET /bower_components/angular-route/angular-route.min.js.map 200 21ms - 9.61kb
GET /bower_components/angular/angular.min.js.map 200 26ms - 264.16kb

界面显示:

angular-start

index.html中配置的链接已经显示,同时welcome.html页面中配置的Welcome Conan_Z,也显示出来了。关于路由和模板配置,请参考文章:AngularJS路由和模板

5. 增加Bootstrap

接下来,增加Bootstrap-v3,让界面好看起来。我们还是有bower来管理Bootstrap的依赖。

通过命令行,增加类库,并写入的bower.json文件


D:\workspace\javascript\angular-basic>bower install bootstrap --save
D:\workspace\javascript\angular-basic>bower install angular-bootstrap --save
  • 修改index.html: 增加css, js的引用
  • 修改welcome.html: 增加bootstrap的效果

修改index.html


<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>Angular-basic</title>
<meta name="description" content="Copyright http://blog.fens.me">
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="styles/main.css">
</head>
<body ng-app="app">

<div class="container">
<h2 class="text-primary">
<a href="http://blog.fens.me/angularjs-express3-bootstarp3/">快速搭建Web环境 Angularjs + Express3 + Bootstarp3</a>
</h2>
<p>http://blog.fens.me/angularjs-express3-bootstarp3</p>

<div class="row">
<div class=".col-lg-12">
<div ng-view></div>
</div>
</div>
</div>

<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="scripts/angular/app.js"></script>
<script src="scripts/angular/controllers.js"></script>

</body>
</html>

修改welcome.html


<hr/>
<form class="form-inline" role="form">
<div class="form-group">
<label>Welcome</label>
<input type="text" class="form-control" ng-model="username" placeholder="Enter email">
</div>
</form>
<p> {{ username }}</p>

angular-bootstrap

这样就用手动的方式的搭建了:Angularjs + Express3 + Bootstrap3的组合。

6. 完整的项目

项目代码已上传的github,项目地址: https://github.com/bsspirit/angular-basic

项目下载及安装


git clone https://github.com/bsspirit/angular-basic
npm install
bower install

项目运行


node app.js

当然,对于大型的Angular项目,我们可以选择用Yeoman的种子构建,请参考文章:AngularJS从构建项目开始

但有时Yeoman的项目,更新不够及时,比如bootstrap已到v3了,种子项目还是bootstrap的v2,而且v3不兼容v2。这时也许手动构建自己的项目,才是更好的选择。

转载请注明出处:
http://blog.fens.me/angularjs-express3-bootstrap3/

打赏作者

AngularJS路由和模板

AngularJS体验式编程系列文章,将介绍如何用angularjs构建一个强大的web前端系统。angularjs是由Google团队开发的一款非常优秀web前端框架。在当前如此多的web框架下,angularjs能脱颖而出,从架构设计上就高人一等,双向数据绑定,依赖注入,指令,MVC,模板。Angular.js创新地把后台技术融入前端开发,扫去jQuery一度的光芒。用angularjs就像写后台代码,更规范,更结构化,更可控。

关于作者

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/angularjs-route-template/

AngularJS-route

前言

如果想开发一款类似gmail的web应用,我们怎么做呢?

以jQuery的思路,做响应式的架构设计时,我们要监听所有点击事件,通过事件函数触发我们加载数据,提交,弹框,验证等的功能;以 AngularJS的思路,做声明式的架构设计时,我们通过指令和路由先设定好,什么样的操作干什么事情,等事件发生时,程序就会知道该干什么了。

今天说一下,AngularJS是如何实现前端路由功能的!

目录

  1. AngularJS路由介绍
  2. 路由的代码实现
  3. 实现效果截图

1. AngularJS路由介绍

AngularJS路由功能是一个纯前端的解决方案,与我们熟悉的后台路由不太一样。后台路由,通过不同的URL会路由到不同的控制器上(controller),再渲染(render)到页面(HTML)。AngularJS的前端路由,需求提前对指定的(ng-app),定义路由规则(routeProvider),然后通过不同的URL,告诉(ng-app)加载哪个页面(HTML),再渲染到(ng-app)视图(ng-view)中。

AngularJS的前端路由,虽然URL输入不一样,页面展示不一样,其实完成的单页(ng-app)视图(ng-view)的局部刷新。这样来看,AngularJS做单页应用就有点标配的感觉了。

从这个角度想想,要实现一个gmail的应用,真的就不难了。

2. 路由的代码实现

理论不多说了,直接上代码!! 还是基于我们之前用yeoman构建的项目

业务场景:论坛功能,帖子列表页(list.html) 和 帖子内容页(detail.html)。

代码文件:

  • 1. 增加:app/demo-route.html
  • 2. 增加:app/views/route/list.html
  • 3. 增加:app/views/route/detail.html
  • 4. 修改: app/scripts/app.js
  • 5. 修改: app/scripts/controllers/main.js

1). 增加:app/demo-route.html
这个文件是主页面(ng-app),包含视图(ng-view)

<!doctype html>
<head>
<meta charset="utf-8">
<title>route</title>
</head>
<body ng-app="routeApp">
<h1>Route Demo index</h1>

<div ng-view></div>

<script src="bower_components/angular/angular.js"></script>
<script src="scripts/app.js"></script>
<script src="scripts/controllers/main.js"></script>
</body>
</html>

2). 增加:app/views/route/list.html
这个页面是布局模板,是HTML的代码片段。包括了一组ID的列表,通过ID列表的链接,可以进入到ID的详细页面。


<hr/>
<h3>Route : List.html</h3>

<ul>
<li ng-repeat="id in [1, 2, 3 ]">
<a href="#/list/{{ id }}"> ID{{ id }}</a>
</li>
</ul>

3). 增加:app/views/route/detail.html
这个页面是布局模板,是HTML的代码片段。通过ID访问,包含ID号, (ID的文章内容)


<hr/>
<h3>Route <span style="color: red;">{{id}}</span>: detail.html </h3>

4). 修改: app/scripts/app.js
这个是ng-app文件的定义,我们在demo-route.html中定义了routeApp,在这里需要声明。


var routeApp = angular.module('routeApp',[]);
routeApp.config(['$routeProvider',function ($routeProvider) {
      $routeProvider
      .when('/list', {
        templateUrl: 'views/route/list.html',
        controller: 'RouteListCtl'
      })
      .when('/list/:id', {
          templateUrl: 'views/route/detail.html',
          controller: 'RouteDetailCtl'
      })
      .otherwise({
        redirectTo: '/list'
      });
}]);

在routeApp模块中,我们定义了路由和布局模板。routeApp的默认URL是/list,即http://localhost:9000/demo-route.html#/list。 跳转详细页的路由是/list/:id,id为参数。

同时,/list的布局模板是views/route/list.html,属于RouteListCtl的控制器管理空间。

5). 修改: app/scripts/controllers/main.js
这个文件定义控制器controller。


routeApp.controller('RouteListCtl',function($scope) {
});
routeApp.controller('RouteDetailCtl',function($scope, $routeParams) {
    $scope.id = $routeParams.id;
});

分别对应该路由中的两个控制器声明。

程序写好,我们打开浏览器看效果。

3. 实现效果截图

别忘了用下面命令,启动程序。

grunt server

浏览器被自动打开,默认出的是http://localhost:9000/demo-route.html#/list, “#/list”是被redirectTo转向的结果。

AngularJS-route1

点击ID2的链接。

AngularJS-route2

页面被刷新了,出了detil的页面。同时,我们注意观察,页面没有整个刷新,而在视图中(ng-view)做的局部刷新。因为,chrome的开发工具的监控中,只是看到detail.html被加载。

我们再浏览地址栏中,输入212

http://localhost:9000/demo-route.html#/list/212

AngularJS-route3

观察chrome的开发工具的监控中,没有任何的networking操作。

在浏览地址栏中,再输入原来list的地址

http://localhost:9000/demo-route.html#/list

观察chrome的开发工具的监控,确认没有任何变化!!

从这个实验,我们看到AngularJS纯前端路由的实现思路,配合视图的局部刷新,把业务功能切片后分散到HTML的模板页面中。非常容易地实现了widget。并且,这种widget可重用性会非常高,能大大减少前端代码量。

后端组件化开发思路,流畅的嵌入前端。爽死啦!!!

转载请注明出处:
http://blog.fens.me/angularjs-route-template/

打赏作者