vue使用driver.js引导页,在vue-element-admin项目汇中

JavaScript017

vue使用driver.js引导页,在vue-element-admin项目汇中,第1张

1.引入依赖

yarn add driver.js -S

或者 npm install dirver.js -S

4.在main.js中挂载到vue上

5.使用:在layout文件里使用

在mouted函数调后端接口去判断当前用户是否是第一次登录,如果是调引导页函数,否则不调

可以使用js,判断浏览器的宽度,然后自动从引导页跳出,或者隐藏引导页等。

if($(document).width() <= 640){ // 这里是jQuery,可以使用原生JS代码。

    location.href = 'xxx' // 自动跳出引导页。

}

总体思路

thinkphp通过RESTful方式提供数据给angular,前端(包括模板页面)全部由angular来接管。

示例

实现一个用户管理模块,走通增删改查4个操作,通过该示例,演示如何在thinkphp中使用AngularJS。

一. 准备工作

1. 加载所需的js和css文件

angular.min.js angular核心库文件

angular-ui-router.min.js angular路由插件angular-resource.min.js负责与服务端restful交互的插件layer弹窗插件,该插件依赖于jQuery-1.10.1.min.js和jquery-ui.min.js两个库文件以及一个jquery-ui.min.css样式表bootstrap.min.css bootstrap核心样式表文件结构如下:

2. 引导页

准备一个angular引导页,angular通过该引导页开启一个angular应用,后续所有的操作,都是基于该引导页进行的。

友情提醒:

这里的引导页,其实就是我们应用的默认页面,具体到thinkphp中,指的就是DEFAULT_MODULE/DEFAULT_CONTROLLER/DEFAULT_ACTION对应的模板文件。第一次访问应用时,thinkphp控制器会定向到该页面,之后的模板页面,全部由angular接管,跟thinkphp的模板引擎就没有半点关系了。

3. 应用首页

在引导页中通过<div ui-view="main"></div>包含我们的应用首页。便签的含义后面会有解释。

注意:这一步不是必须的,因为你也可以把应用首页的内容,全部放在引导页中,但是这样做就不够友好了。

4. 搭建RESTFul环境

为了能够使用$resource,我们必须让服务端按照RESTful的方式来工作,否则,$resource就无法发挥其作用了。

thinkphp中内置了对RESTful的支持,使用方式也很简单,就是让某个Controller继承自RestController,然后按照一定的规则来编写资源方法即可。但是它有一个缺点,thinkphp内置的RESTful对资源的访问方式不够友好,其访问资源的URL结构如下:

/模块名称/控制器名称/资源名称

基于此,我们考虑使用thinkphp的路由功能,来实现对RESTful的支持,使用thinkphp的路由功能时,控制器是没有必要继承RestController的,但为了尊重tp的劳动成果,同时,为了兼顾友好的资源访问方式,最终,我使用的是RestController+路由两者结合的方式。

补充:

资源方法的命名规则为:资源名称_REST类型

REST类型有如下几种:get,post,put,delete5. 创建数据库表

创建用户表,并初始化一些数据

[sql] view plain copy 在CODE上查看代码片派生到我的代码片DROP TABLE IF EXISTS `an_user`

CREATE TABLE `an_user` (

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`user_id` int(10) unsigned NOT NULL COMMENT '用户id',`user_name` varchar(100) NOT NULL COMMENT '用户名称',`email` varchar(255) DEFAULT NULL COMMENT '邮箱地址',`tel` varchar(255) DEFAULT NULL COMMENT '手机号码',`weixin` varchar(255) DEFAULT NULL COMMENT '微信号',`qq` varchar(255) DEFAULT NULL COMMENT 'qq号码',PRIMARY KEY (`id`)

) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='用户表'INSERT INTO `an_user` VALUES ('1', '1', 'demo1', '[email protected]', '13100000000', 'weixin_test1', '123456')INSERT INTO `an_user` VALUES ('2', '2', 'demo2', '[email protected]', '13100000001', 'weixin_test2', '123456')INSERT INTO `an_user` VALUES ('3', '3', 'demo3', '[email protected]', '13100000002', 'weixin_test3', '123456')INSERT INTO `an_user` VALUES ('4', '4', 'demo4', '[email protected]', '13100000003', 'weixin_test4', '123456')INSERT INTO `an_user` VALUES ('5', '5', 'demo5', '[email protected]', '13100000004', 'weixin_test5', '123456')INSERT INTO `an_user` VALUES ('6', '6', 'demo6', '[email protected]', '13100000005', 'weixin_test6', '123456')INSERT INTO `an_user` VALUES ('7', '7', 'demo7', '[email protected]', '13100000006', 'weixin_test7', '123456')INSERT INTO `an_user` VALUES ('8', '8', 'demo8', '[email protected]', '13100000007', 'weixin_test8', '123456')INSERT INTO `an_user` VALUES ('9', '9', 'demo9', '[email protected]', '13100000008', 'weixin_test9', '123456')二. 开始吧

1. 创建引导页

前面说过,引导页其实就是我们应用的默认页面,在我的项目中,默认页面的文件路径为:

/tpl/Admin/Index/index.html

在该文件中,加入如下内容:

[html] view plain copy 在CODE上查看代码片派生到我的代码片<!DOCTYPE html>

<html ng-app="antp">

<head>

<meta charset="utf-8" />

<title></title>

<meta content="width=device-width, initial-scale=1.0" name="viewport" />

<meta content="" name="author" />

<link href="/public/css/bootstrap.min.css" rel="stylesheet" type="text/css" media="all">

<link href="/public/css/jquery-ui.min.css" rel="stylesheet" type="text/css" media="all">

<script type="text/javascript" src="/public/js/angular.min.js"></script>

<script type="text/javascript" src="/public/js/angular-resource.min.js"></script>

<script type="text/javascript" src="/public/js/angular-ui-router.min.js"></script>

<script type="text/javascript" src="/public/js/jquery-1.10.1.min.js"></script>

<script type="text/javascript" src="/public/js/jquery-ui.min.js"></script>

<script type="text/javascript" src="/public/js/layer/layer.js"></script>

<script type="text/javascript" src="/config.js"></script>

<script type="text/javascript" src="/app.js"></script>

<link rel="shortcut icon" href="favicon.ico" />

</head>

<body>

<div class="container-fluid">

<div class="row clearfix">

<div class="col-md-12" style="float: nonedisplay: blockmargin-left: automargin-right: auto">

<div ui-view="main"></div>

</div>

</div>

</div>

</body>

</html>

页面中加载的js和css,除了config.js和app.js,其它的在前面都已经作了说明,这两个后面也会说到。

注意html标签中的ng-app指令,该指令的内容,就是angular要开启的应用名称。

2. 开启应用

之前的index.html文件中,通过ng-app指令定义了一个应用名称,定义完之后,我们还需要开启它,开启的方式也很简单,我们需要创建一个js文件,名称为app.js,在里面先加入如下内容:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片var app = angular.module("antp",["ui.router","ngResource"])其中,module的第二个参数,是angular的一些依赖包。

3. 配置路由

使用ui.router的路由功能,通过config预先配置好访问url、该url对应的视图模板以及控制器等信息,同样是在app.js文件中,继续加入如下内容:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片app.config(function($stateProvider, $urlRouterProvider, $locationProvider) {//启用HTML5模式的路由,该模式下会去除URL中的#号//$locationProvider.html5Mode(true)

//默认页面,所有请求不到的资源,都会转向到这个URL$urlRouterProvider.otherwise("/index")

$stateProvider.state("user", {

url: "/user",

views: {

main: {

templateUrl: "tpl/Admin/User/index.html",controller: "UserCtroller"

}

}

}).state("index", {

url: "/index",

views: {

main: {

templateUrl: "tpl/Admin/Index/main.html",controller: "MainCtroller"

}

}

}).state("user-add", {

url: "/user/add",

views: {

main: {

templateUrl: "tpl/Admin/User/add.html",

controller: "UserFormCtroller"

}

}

}).state("user-edit", {

url: "/user/edit/:user_id",

views: {

main: {

templateUrl: "tpl/Admin/User/add.html",

controller: "UserFormCtroller"

}

}

})

})

还记得之前引导页中的ui-view="main"吗?ui-view的名字,就是state中配置的views下面的属性名称。也许你会说,config里面配置了那么多的main,它是如何知道找的是哪个main?仔细看下代码就知道了。

注意1:控制器controller我们并没有手动写在某个页面的标签上,而是统一配置在了config里。

注意2:每个视图模板必须要对应一个控制器,并且这个控制器必须要被创建,否则,该视图将无法展示。

注意3:不要把此处的控制器和thinkphp里面的控制器搞混,事实上,他们两者之间没有任何关系。

4. 引入每个模块下的js

这里为了便于代码管理与维护,我在每个模块下面创建了一个js文件,每个模块的js完成特定的功能,这些js同样需要在app.js中被引入。

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片document.write('<script type="text/javascript" src="/tpl/Admin/Index/main.js"></script>')document.write('<script type="text/javascript" src="/tpl/Admin/User/user.js"></script>')5. 浏览器访问

在浏览器地址栏中,输入http://local.antp,将会看到如下效果:

仔细观察下地址栏,我们输入的是http://local.antp,但是却自动变成了http://local.antp/#/index,知道为什么吗?

首页,引导页中的<div ui-view="main"></div>,表示我需要路由到main这个视图,但是,我们输入的地址http://local.antp中,并没有告诉angular到底是哪个main,发生这种情况的时候,angular就会定向到默认的视图,默认的视图由$urlRouterProvider.otherwise("/index")这一句来指定。

由于/index指向的是tpl/Admin/Index/main.html,所以此处就会把main.html对应的内容展示出来。

main.html文件内容:

[html] view plain copy 在CODE上查看代码片派生到我的代码片<div ng-include="'tpl/Admin/Public/header.html'"></div>

<blockquote>

<p>

我是默认页面,所有请求不到的资源,都会到我这里来...

</p>

</blockquote>

其中,通过ng-include指令,引入了一个公共导航页面,ng-include指令中双引号内的单引号不可少,内容如下:

[html] view plain copy 在CODE上查看代码片派生到我的代码片<div style="margin-top:20px">

<nav class="navbar navbar-default" role="navigation">

<div class="navbar-header">

<a class="navbar-brand" href="#">Brand</a>

</div>

<div class="collapse navbar-collapse">

<ul class="nav navbar-nav">

<li class="active">

<a ui-sref="user">用户管理</a>

</li>

</ul>

</div>

</nav>

</div>

6. 用户列表

点击导航中的【用户管理】,即可跳转到用户列表页面,如下:

该列表对应的视图文件为tpl/Admin/User/index.html,内容如下:

[html] view plain copy 在CODE上查看代码片派生到我的代码片<div ng-include="'tpl/Admin/Public/header.html'"></div>

<button type="button" class="btn btn-primary" ng-click="addAction()">新增</button>

<table class="table table-bordered table-striped" style="margin-top:15px">

<thead>

<tr>

<th>用户名</th>

<th>邮箱</th>

<th>手机号</th>

<th>微信</th>

<th>QQ</th>

<th>操作</th>

</tr>

</thead>

<tbody>

<tr ng-repeat="user in data.user">

<td>

<a ui-sref="user-edit({user_id:user.user_id})" ng-bind="user.user_name"></a>

</td>

<td ng-bind="user.email"></td>

<td ng-bind="user.tel"></td>

<td ng-bind="user.weixin"></td>

<td ng-bind="user.qq"></td>

<td>

<button type="button" class="btn btn-link">

<a ui-sref="user-edit({user_id:user.user_id})">修改</a>

</button>

<button type="button" class="btn btn-link" ng-click="deleteAction(user.user_id)">删除</button>

</td>

</tr>

</tbody>

</table>

为了能够从后端拿到数据,我们需要创建一个$resource资源,创建方式如下:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片//通过factory创建一个service,该service通过$resource返回了一个资源对象//$resource负责与支持restful的服务端进行数据交互app.factory("UserService", function($resource) {return $resource(globalConfig.API.URL + "users/:id", {id: "@id"

},

{

//query方法要求服务端返回的数据格式为数组,如果返回的是非数组格式,需要在transformResponse函数中作转换处理query: {

method: "GET",

isArray: true,

transformResponse: function(data) {

return JSON.parse(data)

}

},

update: {

method: "PUT"

}

})

})

这里,创建了一个名字为UserService的资源,然后,我们还需要创建一个控制器,将UserService资源注入进去,代码如下:

[javascript] view plain copy 在CODE上查看代码片派生到我的代码片//用户列表Ctroller

app.controller('UserCtroller', function($scope, $state, UserService) {$scope.data = {}

//获取用户列表

UserService.query().$promise.then(

function(data){

//将查询结果赋值给data.user,模板中可以对data.user变量进行遍历$scope.data.user = data

},

function(error) {

console.log("An error occurred", error)

}

)

$scope.addAction = function() {

$state.go("user-add")

}

$scope.deleteAction = function(user_id){

layer.confirm("确定要删除该用户吗", {

btn: ['确定','取消']

}, function(index){

layer.close(index)

UserService.remove({id:user_id}).$promise.then(function(res){

if(res.status){

$state.go("user",null,{

reload:true

})

}else{

}

},

function(error) {

console.log("An error occurred", error)

}

)

})

}

})

通过UserService的query方法,获取用户列表信息。

7. 新增用户

点击列表上的【新增】,将会通过$state.Go("user-add")跳转到新增页面:

该页面对应的视图文件为tpl/Admin/User/add.html,内容如下:

[html] view plain copy 在CODE上查看代码片派生到我的代码片<div ng-include="'tpl/Admin/Public/header.html'"></div>

<form class="form-horizontal" role="form" name="userForm">