三剑客+Jquery.ajax+VUE单页+ThinkPHP3.2.3的前后端分离开发

说明

这篇博客是给团队内人员的一个模式开发的说明文档,当然对于其他读者也可以了解,不喜勿喷

前言

其实,这种开发模式还是挺少见的,vue自有vue-cli可以使用webpack打包前端项目,然后后端就做后端的活提供数据服务,这样前后端分离的彻底,但是限于笔者个人水平,vue-cli和webpack正在学习中,所以替代的方案,就是这种看起来怪怪的组合,不过实验证明是可行的方案,缺点就是前后分离不是很彻底,毕竟前端的访问路由由thinkPHP框架做了,这样从某种意义上说,前后还是没有完全的分开,但是基本上已经实现了业务和数据的分离

简单介绍一下这种模式

1、三剑客就是HTML+CSS+JS,当然也包含了一些纯HTML的前端框架,比如bootstrap3、easyUI等,这些在项目中使用都是没关系的,不会影响到整体模式的配合

2、Jquery.ajax就是jquery中关于ajax方法的支持,通过ajax来做异步的请求处理,这也是实现前后端分离、业务和数据分离、面向数据编程的关键之处,通过ajax的请求直接对后台的数据接口进行访问,也就是说后台不需要在把变量assign到对应的页面了,而是前端需要数据的时候去访问后台获取数据,我们也可以看到这其实是主动权的一个转换,主动权从后端转向了前端,从要不要都要给变为了需要了再去取
【jQuery.ajax 注意】:这里我要说明一点,vue是数据驱动的框架,jQuery则是偏向于强大而简洁的DOM操作,这两个框架编程的方式大相径庭,我们这里使用了以数据驱动为主的vue,就不需要在使用jQuery的DOM操作了,但是之所以引入Jquery是因为vue自身并不支持Ajax请求,其实vue有一个叫vue-resource的插件可以使用更简洁的API来使用Ajax,但是因为jQuery更容易上手,所以这次使用jQuery.ajax作为发起request的方式

3、VUE单页就是使用VUE做单页的应用,在这种模式下的意思就是在每个页面都引入VUE,路由则交给ThinkPHP框架去做。
我目前对于VUE的认识有两点,一是VUE是一个渐进式框架,所谓渐进式我的理解就是你可以慢慢一点一点的上手,举个例子,比如ThinkPHP这种框架,如果你一开始是写的原生PHP,突然转到使用ThinkPHP框架,你需要先看完整个框架的说明并且使用框架,才能成功搭建你的项目(当然这个例子不是很好,一个是JS框架,一个是PHP框架,我只是想说明渐进式这种概念,笔者也是正在学习VUE的路途中,可能有些错误望指正),但是VUE不是这样的,你只需要学一点用一点就可以,而且VUE的使用并不会影响你其他东西的使用,其他的东西还是按照你的习惯就可以;二是VUE是一个数据驱动的框架,而且有些打破传统的DOM操作的一些特性,比如说,动态数据绑定(比如mustache语法的支持,v指令对数据/事件的绑定等)以及对自定义组件和模板的支持等待,大大提高了前端处理业务的能力,以至于现在很多前端技术比如我们熟知的微信小程序、还有大公司常用的reactJS和AngularJS,包括我们用的VUE都是前端渲染的框架,传统的基于DOM的开发方式比较费时费力而且代码冗余难以维护,所以前端渲染的模式也是一种趋势

4、最后说一下ThinkPHP,ThinkPHP是一个快速、兼容而且简单的轻量级国产PHP开发框架,相对比较友好的一个PHP框架(对比yii来说),因为是国产的,中文文档很详实,版本更新已经到5.x了,我们此次使用的是ThinkPHP3.2.3

总: 我们此次这种模式下,各个框架的作用是什么或者说各个框架承担的角色是什么呢?
三剑客就是负责网页的结构布局和样式,甚至是动画效果(VUE中也有过渡动画可以使用,但是鉴于大家刚入坑不久,我们先不使用)
Jquery.ajax就是负责异步请求
VUE是做业务处理和视图更新
ThinkPHP是做路由和后台数据服务

精简的教程

三剑客不再说了,为了大家方便,我下面以demo实例的方式做一个这种模式下的精简教程

Jquery.ajax

Ajax的产生初衷是为了解决局部刷新的问题,在传统的后端渲染的模式下,用户在前端交互时因为需要后端去做处理并重新加载至页面,所以往往会出现“闪屏”的问题,网速差的话,这种问题就暴露的更明显,所以Ajax技术就通过前端发送一个伪请求(模拟get和post请求)的方式向后端请求数据包,一般来说这个数据包其实就是一个字符串或者对象,这个字符串或者对象的类型有三种,分别是text、json和XML,我们这里就是json字符串和json对象。前端获取到数据包后,通过json的解析方法可以解析出相应的数据结构,再通过js对前端的数据进行刷新,这种方式下,页面不会出现“闪屏”的问题。
原生的ajax用起来不是很方便,Jquery对原生ajax进行封装,给出了$.get、$.post和通用的$.ajax方法,我们用$.ajax就行了,下面是简单的demo

     $.ajax({
      url : "{:U('Index/searchBook')}",
      type : "post",
      contentType : "application/x-www-form-urlencoded;charset=utf-8",
      data : {
       text : that.text
      },
      dataType : "json",
      success : function(data){
       
       if(data.code == 'success'){
        //将json字符串转为json对象
        var jsonStr = data.data
        //去掉字符串中的空格
        jsonStr = jsonStr.replace(" ","");
       	//typeof https://www.cnblogs.com/liu-fei-fei/p/7715870.html
        if(typeof jsonStr!='object'){
        //去掉饭斜杠
        jsonStr = jsonStr.replace(/\ufeff/g,"")
                       var jsonObj = JSON.parse(jsonStr)
                       that.booklist = jsonObj
       }
       }
       if(data.code == 'fail'){
        layer.msg(data.msg)
       }
      }
     })

$.ajax还有其他的一些不常用的属性,想了解可以看这篇博客 :
https://www.cnblogs.com/jackcheblog/p/7065421.html

当data中text=9787561231944时,这是返回的json对象

扫描二维码关注公众号,回复: 9478283 查看本文章
{
  "code": "success",
  "data": "[{\"book_id\":\"1531-5\",\"isbn\":\"9787561231944\",\"title\":\"\\u8f6f\\u4ef6\\u7cfb\\u7edf\\u5f00\\u53d1\\u6307\\u5bfc\\u4e66\",\"author\":\"\\u90d1\\u4f1f\",\"theme\":\"\\u8f6f\\u4ef6\\u5f00\\u53d1\\u7cfb\\u5217\\u4e1b\\u4e66\",\"category\":\"\\u79d1\\u6280\\u7c7b\",\"abstract\":\"\\u8f6f\\u4ef6\\u6d4b\\u8bd5\\u662f\\u8f6f\\u4ef6\\u5de5\\u7a0b\\u5b66\\u79d1\\u7684\\u4e00\\u4e2a\\u91cd\\u8981\\u5206\\u652f\",\"publisher\":\"\\u897f\\u5317\\u5de5\\u4e1a\\u5927\\u5b66\\u51fa\\u7248\\u793e\",\"pub_date\":\"2011-06-10\",\"language\":\"zh_CN\"}]"
}

我们可以通过data.code或者data.data来直接访问到键对应的值,data中的数据是一个json字符串,所以需要先转换为json对象才能使用.来访问键值对

Vue单页

我们这次的项目使用的是最基本的Vue,有关组件和模板以及构建工具这方面先不涉及

在html中创建一个vue实例

<!DOCTYPE html>
<html>
<head>
<!-- 首先需要引入vue框架文件 -->
<script type="text/javascript" src="__ROOT__/public/syspkg/vue.js"></script>
</head>
<body>
	<div id="home">
		<div>{{text}}</div>
		<div v-on:click="A"></div>
	</div>
	<script type="text/javascript">
		var app = new Vue({
		   el : '#home',
		   data : {
		    text : "创建第一个vue",
		   },
		   methods : {
		   	A : function(){
				alert(this.text)
			}
		   }
	</script>
</body>
</html>

因为vue需要挂载dom节点,所以vue的创建需要在dom结构之后才能真正被实例化,从这个例子中你可以看到所谓数据驱动的意思就是无论是dom元素还是dom的原生事件,vue都是通过data来封装数据,通过methods来驱动数据处理业务,当然一个vue实例中还有其他的驱动方式,如计算属性/侦听器等,这个在有能力的基础上可以自行学习使用

更详细的教程官方文档上比我说的要清楚许多,可以自行查看:vue.js官方教程

我在这里说下对于vue中数组的使用,以及我们要做列表渲染和列表的增删时如何做

vue中data属性中数组(es5语法)其实和json很像,这也是为什么json对象可以直接赋值给vue的数组使用

下面以一个图书管理的表格的增删查为例,改就不说了,和增删差不多的

html

    <table class="table table-bordered">
     <thead> 
      <tr>
       <th>book_id</th>
       <th>ISBN</th>
       <th>Title</th>
       <th>Author</th>
       <th>Theme</th>
       <th>Category</th>
       <th>Abstract</th>
       <th>Publisher</th>
       <th>PubDate</th>
       <th>Language</th>
       <th>options   </th>
      </tr>
     </thead>
     <tbody id="add">
      <tr v-for="(book,index) in booklist" >
       <td>{{book.book_id}}</td>
       <td>{{book.isbn}}</td>
       <td>{{book.title}}</td>
       <td>{{book.author}}</td>
       <td>{{book.theme}}</td>
       <td>{{book.category}}</td>
       <td>{{book.abstract}}</td>
       <td>{{book.publisher}}</td>
       <td>{{book.pub_date}}</td>
       <td>{{book.language}}</td>
       <td><a href="javascript:void(0);" v-on:click="removeBook(index)">delete</a> | <a href="javascript:void(0);" v-on:click="updateBook(index)">modify</a></td>
      </tr>
     </tbody>
    </table>

vue.js

var app = new Vue({
   el : '#home',
   data : {
     booklist : [],
   }
   created : function(){

    var that = this
     $.ajax({
      url : "{:U('Index/getBook')}",
      dataType : "json",
      success : function(data){
       if(data.code == 'success'){
        
        //将json字符串转为json对象
        var jsonStr = data.data
        //去掉字符串中的空格
         jsonStr = jsonStr.replace(" ","");
         //typeof https://www.cnblogs.com/liu-fei-fei/p/7715870.html
         if(typeof jsonStr!='object'){
         //去掉饭斜杠
          jsonStr = jsonStr.replace(/\ufeff/g,"")
          var jsonObj = JSON.parse(jsonStr)
           that.booklist = jsonObj
          }
                          
        }
       if(data.code == 'fail'){
        layer.msg(data.msg)
       }
      }
     })
   },
   methods : {
   	    addBook : function(event){
     var that = this
     layer.open({
      type : 2,
      title: 'add',
                     shadeClose: true,
                     shade: 0.8,
                     area: ['480px', '540px'],
                     content: "{:U('Index/add')}" ,//iframe的url
                     success : function(layero,index){
                      var submit = layer.getChildFrame('#submit',index);
                      submit.click(function(){
                       var book_id = layer.getChildFrame('#book_id',index).val();
                       var ISBN = layer.getChildFrame('#ISBN',index).val();
                       var title = layer.getChildFrame('#title',index).val();
                       var author = layer.getChildFrame('#author',index).val();
                       var theme = layer.getChildFrame('#theme',index).val();
                       var category = layer.getChildFrame('#category',index).val();
                       var abstract = layer.getChildFrame('#abstract',index).val();
                       var publisher = layer.getChildFrame('#publisher',index).val();
                       var pub_date = layer.getChildFrame('#pub_date',index).val();
                       var language = layer.getChildFrame('#language',index).val();
			
		      $.ajax({
         url : "{:U('Index/addBook')}",
         type : "post",
         contentType : "application/x-www-form-urlencoded;charset=utf-8",
         data : {
          book_id : book_id,
          ISBN : ISBN,
          title : title,
          author : author,
          theme : theme,
          category : category,
          abstract : abstract,
          publisher : publisher,
          pub_date : pub_date,
          language : language,
         },
         dataType : "json",
         success : function(data){
          
          if(data.code == 'success'){
           
           layer.close(layer.index)
           //将json字符串转为json对象
           var arr = [
            {
             book_id : book_id,
             isbn : ISBN,
             title : title,
             author : author,
             theme : theme,
             category : category,
             abstract : abstract,
             publisher : publisher,
             pub_date : pub_date,
             language : language,
            }
           ]
	 var jsonStr = JSON.stringify(arr)
	  //去掉字符串中的空格
	   jsonStr = jsonStr.replace(" ","")
	    //typeof https://www.cnblogs.com/liu-fei-fei/p/7715870.html
	    if(typeof jsonStr!='object'){
	     //去掉饭斜杠
	    jsonStr = jsonStr.replace(/\ufeff/g,"")
                                       var jsonObj = JSON.parse(jsonStr)
                                       that.booklist.unshift(jsonObj[0])
	}
                                     layer.msg(data.msg)
          }
          if(data.code == 'fail'){
           layer.close(layer.index)
           layer.msg(data.msg)
          }
         }
        })
        })
	}
	})
},
    removeBook : function(index){
     var that = this
     var book_id = that.booklist[index].book_id
     $.ajax({
      url : "{:U('Index/removeBook')}",
      type : "post",
      contentType : "application/x-www-form-urlencoded;charset=utf-8",
      data : {
       book_id : book_id
        },
      dataType : "json",
      success : function(data){
       if(data.code == 'success'){
        that.booklist.splice(index,1)
        layer.msg(data.msg)
       }
       if(data.code == 'fail'){
        layer.msg(data.msg)
       }
      }
     })
    },
   }
   

说明三点:
1、这里添加的时候,加入了一个layer的弹窗,这个可以忽略,我想强调的是,添加和删除一本书的瘦,不要再$.ajax的success回调函数中使用jQuery的dom操作来做前端的展示效果,善用js数组对象的方法,比如unshift()、push()、splice()等方法来对数据做处理,然后使用vue的数据绑定帮助你做视图的更新,有关js数组方法看下面:
http://www.w3school.com.cn/jsref/jsref_obj_array.asp
2、去了解以下vue实例的生命周期和对应的钩子函数的概念,这对于首屏加载和初始化参数很有用
3、注意到我v-for的写法:<tr v-for="(book,index) in booklist">,这里的index,是指当前数组的下标,这里是为了标识你的remove点击事件的对象或者说是标识你要删除数组中的哪一项,笔者这里也表示困惑,因为之前开发小程序,有dataset这样的自定义属性,可以在methods的方法中获取原生事件的target或者currenttarget属性从而判断当前数组的下标,但是vue中并不知道如何获取到原生事件的属性,这个我在研究学习一下,后期更新…

ThinkPHP3.2.3

这个不再这里详述,中文的官方文档很详实,本次大家不用学习全部的框架知识,只需要有一定的PHP基本语法基础就好,我已经搭好框架,按照我写的接口,写相应的函数就好了

举个例子:

/*
  * searchBook
  * http://localhost/libSys/index.php?s=/Home/Index/searchBook  或者使用tp模板路由 {:U('Home/Index/searchBook')}
  * {
  *  text [ISBN/title]
  * }
  * {
  *  code : "success" / "fail"
  *  data : {
  *      book_id [图书唯一码]
  *        ISBN 
  *         title
  *          author
  *           theme
  *           category
  *           abstract
  *           publisher
  *           pub_date
  *           language [使用国际标准语言缩写,如中国=>zh_CN]
  *    }
  *  }
 */
public function searchBook(){
   if(cookie('staffAccount') != ''){
    $text = $_POST['text'];
    $return = array();
    $book = D('Book');
    if(is_numeric($text) && strlen($text)==13){
	//ISBN
	$sql = "select * from lib_book where ISBN='{$text}' ";
     $return = $book->query($sql);
     }else{
     //title
     $text = '%'.$text.'%';
     $sql = "select * from lib_book where title like '{$text}' ";
     $return = $book->query($sql);
     }
     if($return){
     $json = json_encode(array(
        'code' => 'success',
        'data' => json_encode($return)
      ));
      echo $json;
      }else{
     $json = json_encode(array(
       'code' => 'fail',
       'msg' => '查询sql出错'
      ));
    }
    }else{
   $json = json_encode(array(
     'code' => 'fail',
     'msg' => 'cookie过期'
    ));
   echo $json;
  }
   
  }

说明三点:
1、返回数据格式必须为json,这个php的json_encode给我们提供了方便,我们直接去格式化PHP数组就可转为json数据包,返回的json格式尽量和我保持一致,code字段表示的状态,msg表示的是对应的提示信息,data则是需要展示的数据包
2、注释部分就是我写的接口,从上到下依次是,函数名,访问接口,需要的POST参数列表,返回的json参数列表
3、关于D方法,这个方法是实例化数据库中的一张表,例如D(‘Book’),是去实例化lib_book这个表,lib_前缀字段我已经配置好了,若想去做数据库访问操作,直接D方法对应的数据库表名的后半段就行了,再举个例子比如实例化lib_vipvard这张表,只需D(‘Vipcard’),注意首字母大写;另外,query()方法去执行select查询语句,execute()去执行update、insert、delete更新语句

总算啰嗦完了,祝大家好运,不懂的可以来问我!

发布了65 篇原创文章 · 获赞 58 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/AngelLover2017/article/details/82966458