jquery ajax thinkphp異步局部刷新完整流程

環境:ThinkPHP3.2.3,jQuery3.2
 
前言:
在通常的網站中,都須要用到jquery或者其餘框架(好比angular)來處理先後端數據交互,thinkphp在後臺也內置了一些函數用於數據交互(好比ajaxReturn())。本文的目的是打通使用ajax在jquery和thinkphp之間的先後端數據交互過程。
 
正文:
1、thinkphp關於ajax的介紹
1.1 ajaxReturn:
\Think\Controller類提供了ajaxReturn方法用於AJAX返回數據給客戶端(視圖、模板、js等)。而且支持JSON、JSONP、XML和EVAL四種方式給客戶端接受數據(默認JSON)。
配置方式:convention.php中定義了默認編碼類型爲DEFAULT_AJAX_RETURN => 'JSON',
分析:ajaxReturn()調用了json_encode()將數值轉換成json數據存儲格式,經常使用的數值是數組。
注意:The value being encoded can be any type except a resource(資源文件).All string data must be UTF-8 encoded.
舉例:
$data['status'] = 1;
$data['content'] = 'content';
$this->ajaxReturn($data);
1.2 請求類型:
系統內置了一些常量用於判斷請求類型,好比:
常量 說明
IS_GET 判斷是不是GET方式提交
IS_POST 判斷是不是POST方式提交
IS_PUT 判斷是不是PUT方式提交
IS_DELETE 判斷是不是DELETE方式提交
IS_AJAX 判斷是不是AJAX提交
REQUEST_METHOD 當前提交類型
目的:一方面能夠針對請求類型做出不一樣的邏輯處理,另一方面能夠過濾不安全的請求。
使用方法:
class UserController extends Controller{
     public function update(){
         if (IS_POST){
             $User = M('User');
             $User->create();
             $User->save();
             $this->success('保存完成');
         }else{
             $this->error('非法請求');
         }
    return 0;
     }
}

1.3 跳轉和重定向:javascript

功能比較雞肋,在ajax異步交互局部刷新中,不須要有文字提示的跳轉。(連接: http://document.thinkphp.cn/manual_3_2.html#page_jump_redirect
 
2、jQuery Ajax的介紹:
2.1 官網關於jQuery.ajax()的介紹:
jQuery.ajax() 方法用於執行 AJAX(異步 HTTP)請求。(連接: http://www.jquery123.com/jQuery.ajax/
語法:$.ajax({name:value, name:value, ... }),該參數規定 AJAX 請求的一個或多個名稱/值對。
常見參數:
type (默認: 'GET')
類型: String
請求方式 ("POST" 或 "GET"), 默認爲 "GET"。注意:其它 HTTP 請求方法,如 PUT 和 DELETE 也可使用,但僅部分瀏覽器支持。
url (默認: 當前頁面地址)
類型: String
發送請求的地址。
async (默認: true)(1.8版本已棄用)
類型: Boolean
默認設置下,全部請求均爲異步請求(也就是說這是默認設置爲 true )。若是須要發送同步請求,請將此選項設置爲 false 。
data
類型: Object, String
發送到服務器的數據。將自動轉換爲請求字符串格式。GET 請求中將附加在 URL 後面。查看 processData 選項說明,以禁止此自動轉換。對象必須爲"{鍵:值}"格式。若是這個參數是一個數組,jQuery會按照traditional 參數的值, 將自動轉化爲一個同名的多值查詢字符串(查看下面的說明)。注:如 {foo:["bar1", "bar2"]} 轉換爲 '&foo=bar1&foo=bar2'。
dataType (默認: Intelligent Guess (xml, json, script, or html))
類型: String
預期服務器返回的數據類型。若是不指定,jQuery 將自動根據 HTTP 包 MIME 信息來智能判斷,好比XML MIME類型就被識別爲XML。在1.4中,JSON就會生成一個JavaScript對象,而script則會執行這個腳本。隨後服務器端返回的數據會根據這個值解析後,傳遞給回調函數。舉例:
"json": 把響應的結果看成 JSON 執行,並返回一個JavaScript對象。在 jQuery 1.4 中,JSON 格式的數據以嚴格的方式解析,若是格式有錯誤,jQuery都會被拒絕並拋出一個解析錯誤的異常。(見json.org的更多信息,正確的JSON格式。)
error
類型: Function( jqXHR jqXHR, String textStatus, String errorThrown )
請求失敗時調用此函數。有如下三個參數:jqXHR (在 jQuery 1.4.x前爲XMLHttpRequest) 對象、描述發生錯誤類型的一個字符串 和 捕獲的異常對象。若是發生了錯誤,錯誤信息(第二個參數)除了獲得null以外,還多是"timeout", "error", "abort" ,和 "parsererror"。 當一個HTTP錯誤發生時,errorThrown 接收HTTP狀態的文本部分,好比: "Not Found"(沒有找到) 或者 "Internal Server Error."(服務器內部錯誤)。 從jQuery 1.5開始, 在error設置能夠接受函數組成的數組。每一個函數將被依次調用。 注意:此處理程序在跨域腳本和JSONP形式的請求時不被調用。這是一個 Ajax Event。
success
類型: Function( Object data, String textStatus, jqXHR jqXHR )
請求成功後的回調函數。這個函數傳遞3個參數:從服務器返回的數據,並根據dataType參數進行處理後的數據,一個描述狀態的字符串;還有 jqXHR(在jQuery 1.4.x前爲XMLHttpRequest) 對象 。在jQuery 1.5, 成功設置能夠接受一個函數數組。每一個函數將被依次調用。這是一個 Ajax Event
其餘jQuery-ajax-settings,詳見:http://www.jquery123.com/#jQuery-ajax-settings
jQuery重要參數

舉例:php

在js中把id做爲數據發送到服務器, 保存一些數據到服務器上, 一旦請求完成就通知用戶。 若是請求失敗,則提醒用戶。
var menuId = $("ul.nav").first().attr("id");
var request = $.ajax({
  url: "script.php",
  type: "POST",
  data: {id : menuId},
  dataType: "html"
}); 
request.done(function(msg) {
  $("#log").html( msg );
}); 
request.fail(function(jqXHR, textStatus) {
  alert( "Request failed: " + textStatus );
});

注意:此處也能夠在ajax()中使用success和error參數判斷請求結果成功仍是失敗,並執行下一步操做。html

 
2.2 js與json
2.2.1 json是什麼:
JSON:JavaScript 對象表示法(JavaScript Object Notation)。是獨立於語言以外的存儲和交換文本信息的語法。
2.2.2 json和ajax的關係?
在上面關於jquery.ajax的介紹中提到了,json能夠做爲一個ajax函數的dataType,這樣數據就會經過json語法傳輸了。(連接: http://www.cnblogs.com/haitao-fan/p/3908973.html
在jquery的ajax函數中,只能傳入3種類型的數據:(連接: http://www.cnblogs.com/haitao-fan/p/3908973.html
>1.json字符串:"uname=alice&mobileIpt=110&birthday=1983-05-12"
>2.json對象:{uanme:'vic',mobileIpt:'110',birthday:'2013-11-11'}
>3.json數組:
[
{"name":"uname","value":"alice"},
{"name":"mobileIpt","value":"110"},
{"name":"birthday","value":"2012-11-11"}
]
2.2.3 json的編解碼和數據轉換:
2.2.2中提到的json對象是更方便與js數組、js字符串或php數組、php字符串進行數據轉化的json類型。下面以json對象爲例講解一下json對象與js和php的數據類型轉化。
json對象轉化成數組:
<script type="text/javascript">
     var jsonStr = '[{"id":"01","open":false,"pId":"0","name":"A部門"},{"id":"01","open":false,"pId":"0","name":"A部門"},{"id":"011","open":false,"pId":"01","name":"A部門"},{"id":"03","open":false,"pId":"0","name":"A部門"},{"id":"04","open":false,"pId":"0","name":"A部門"}, {"id":"05","open":false,"pId":"0","name":"A部門"}, {"id":"06","open":false,"pId":"0","name":"A部門"}]';
     //  var jsonObj = $.parseJSON(jsonStr);
     var jsonObj =  JSON.parse(jsonStr)
     console.log(jsonObj)
     var jsonStr1 = JSON.stringify(jsonObj)
     console.log(jsonStr1+"jsonStr1")
     var jsonArr = [];
     for(var i =0 ;i < jsonObj.length;i++){
            jsonArr[i] = jsonObj[i];
     }
     console.log(typeof(jsonArr))
</script>

想要將表單數據提交到後臺,須要先從表單獲取數據/數據集:java

serialize和serializeArray的區別是serialize()獲取到序列化的表單值字符串,serializeArray()以數組形式輸出序列化表單值。舉例:
var serialize_string=$('#form').serialize();
獲得:a=1&b=2&c=3&d=4&e=5
var serialize_string_array=$('#form').serializeArray();
獲得:
[
{name: 'firstname', value: 'Hello'},
{name: 'lastname', value: 'World'},
{name: 'alias'}, // 值爲空
]
相對來講,serializeArray()和最終想要獲得的json數組更加類似。只不過須要將包含多個name-value形式json對象的json數組改寫成'first_name':'Hello'形式的json對象。
這裏使用第一種方法舉例,傳入的參數是serializeArray()函數的結果,而且稍做優化,能夠起名爲change_serialize_to_json():
function change_serialize_to_json(serialize_objective_array) {
    var temp_json_object = {};
    $.each(serialize_objective_array, function () {
        temp_json_object[this.name] = this.value;
    });
    return temp_json_object;
}

輸出:{"input1":"","textarea":"234","select":"1"}jquery

 
2.2.4完整流程:
var serialize_array=$('#form').serializeArray()結果(結果是json對象數組):
Array [ Object, Object ]
var data=change_serialize_to_json(serialize_array)的結果是(以第二種轉換方法爲例,結果是json對象):
Object {serial_number: "SN2", result: "非法" }
var json_data=JSON.stringify(data)(結果是json字符串):
{"serial_number":"SN2","result":"非法"}
 
在js端將表單數據轉化爲json形式的其餘函數:
將json字符串轉換爲json對象:
eval("(" + status_process+ ")");
json字符串轉化成json對象:
// jquery的方法
var jsonObj = $.parseJSON(jsonStr)
//js 的方法
var jsonObj =  JSON.parse(jsonStr)
json對象轉化成json字符串:
//js方法
var jsonStr1 = JSON.stringify(jsonObj)
JSON.parse()用於從一個字符串中解析出json對象。JSON.stringify()相反,用於從一個對象解析出字符串。
 
str_replace() 函數用於替換掉字符串中的特定字符,好比替換掉數據轉換後多餘的空格、'/nbsp'等
 
注意:serialize和serializeArray()函數在處理checkbox時存在沒法獲取未勾選項的bug,須要本身編寫函數改寫原函數,舉例:
(連接:http://www.cnblogs.com/tangge/p/6554891.html)
//value賦值爲off是由於正常的serializeArray()獲取到的勾選的checkbox值爲on。
$.fn.my_serialize_array = function () {
    var my_serialize_array = this.serializeArray();//官方函數只包含勾選的checkbox,而且值默認爲on
    var not_checked_object = $('input[type=checkbox]:not(:checked)', this);//this指調用這個函數的form
    $.each(not_checked_object, function () {
        if (!my_serialize_array.hasOwnProperty(this.name))
        {//this指沒選中的一個object
            my_serialize_array.push({name: this.name, value: "off"});
        }
    });
    console.log(my_serialize_array);
    return my_serialize_array;
};

 

3、使用js操做DOM實現異步局部刷新的完整流程:
實現局部刷新的途徑:
一、假設頁面有查詢form和結果table。
二、點擊查詢form的提交,觸發js自定義的submit事件,在submit函數中對獲取的表單數據檢測後若是符合要求就傳遞給控制器,控制器從數據庫獲取結果數組後返回給ajax的success。對返回給ajax的結果數組,能夠建立一個refresh()函數,或直接在success中用jQuery(或其餘js)操縱結果table(DOM),好比刪除tbody節點下的全部內容,並將結果數組格式化後添加到tbody下面。
舉例:
//一、php中的form表單
<div class="modal fade hide" id="add_engineer_modal" tabindex="-1" role="dialog">
......
<form id="add_engineer_modal_form" class="form-horizontal">
<fieldset>
......
<button type="button" class="btn btn-primary" id="add_engineer_modal_submit" onclick="add_engineer_modal_submit()" >提交更改</button>
......
</fieldset>
</form>
</div>

 

//二、js校驗表單併發起ajax
function add_engineer_modal_check_value() {
    //以edit_modal_check_value()爲模板
    var serialize_array_object = $("#add_engineer_modal_form").mySerializeArray();//針對checkbox優化的SerializeArray
    var data = change_serialize_to_json(serialize_array_object);
    var check_results = [];
    check_results['result'] = [];//保存錯誤信息
    check_results['data'] = data;//保存input和select對象
    //check_employee_number是自定義判斷員工號函數。
    if (check_employee_number(data['employee_number']) == false)
    {
        check_results['result'].push("請輸入有效的員工號(可選)");
    }
    return check_results;
}

function add_engineer_modal_submit() {
    var check_results = add_engineer_modal_check_value();
    if (check_results['result'].length == 0)
    {
    //注意,是否要轉換上面的data,要取決於你想要用什麼類型傳輸,用js對象傳輸更好,不須要stringify,也方便控制器處理。個人舊代碼有些累贅了。
        var json_data = JSON.stringify(check_results['data']);   //JSON.stringify() 方法將一個JavaScript值轉換爲一個JSON字符串(ajax要求json對象或json字符串才能傳輸)
        $.ajax({
            type: 'POST',
            url: add_engineer_url,        //在php中全局定義url,方便使用thinkphp的U方法
            data: {"json_data": json_data},            //ajax要求json對象或json字符串才能傳輸,json_data只是json字符串而已。若是上面用js對象傳輸,這裏就寫成"data:json_data,"
            dataType: "json",
            success: function (data) {
                console.log("數據交互成功");
            },
            error: function (data) {
                console.log("數據交互失敗");
            }
        });
    }
    else
    {
        //彈出錯誤提示alert
    }
    return 0;
}
注意:此處的add_engineer_url通常定義在函數以前,因爲我有不少函數可能要用到這個url,我通常寫在js最前面。固然也能夠寫在php的head以內,那樣就可使用U方法自動生成url。
 
三、控制器檢查數據操做數據庫並返回數組給js
public function add_engineer() {
        if (IS_AJAX)
        {
            $posted_json_data = I('post.json_data');
            $posted_json_data_replace = str_replace('"', '"', $posted_json_data);//慎用str_replace,若是非要用最好在轉成數組以後,針對特定的item替換。舊代碼這樣寫不太好。
            $posted_json_data_replace_array = (Array)json_decode($posted_json_data_replace);//通常不須要強制Array,json_decode的返回值就是Array,此處我是爲了防止本身的serializeArray產生了特殊值影響到這裏。最好還要有一些過濾函數過濾掉script、html元素等
               
               //處理數據庫事務寫入,經過判斷寫入結果來區分ajaxReturn的結果
              //能夠將全部想要返回的數據放在一個數組中,好比新增的行id、插入數據庫的操做是否成功
              //若是操做數據庫成功就返回以下結果。
               $user_table->commit();//省略事務等操做
            $data['result'] = true;
            $data['pk_user_id'] = $data_add_user_result;
            $this->ajaxReturn($data);//省略條件判斷,建議對正反條件都返回數組,好比$data['alert']記錄返回結果true仍是false,若是是true,就把$data['result']=$result,返回$data。
        }
        return 0;
    }
注意:必定不要在有ajaxReturn的函數中添加打印(echo、var_dump等),這會致使ajax error。若是要在F12下調試,能夠註釋掉ajaxReturn,也能夠直接看交互過程的錯誤提示。
 
四、改寫js:
在js的ajax中,若是整個ajax正常交互,就會走success函數,不然會走error函數,通常狀況下,error出現的緣由都是傳輸的數據不符合要求。
在success中的data就是ajaxReturn中傳輸的數組,舉例:
success: function (data) {
                if (data['result'] == false)
                {
                    alert(data['alert']);
                }
                else
                {
                    $('#add_engineer_modal').modal('hide');
                    $('#user_list_table tr').eq(0).after('<tr></tr>');
                    //這裏就可使用data['pk_user_id']了。
                    $('#user_list_table tr').eq(1).append('<td>'+data['pk_user_id']+'</td>');
                }
            },
  
4、總結
整個過程是:
在php中編寫頁面中的表單、提交按鈕等;
在js中對php中的按鈕事件添加校驗和觸發函數,在js函數內,若是js對象的格式和內容正確就向控制器url(php中初始化)發起ajax請求;
控制器中的相應操做響應ajax請求,並判斷數據後作數據庫讀寫操做,而後對數據庫操做結果作出判斷,ajaxReturn返回js須要的數組;
當ajax成功返回時,js中ajax的success裏面使用js重寫(或初始化)須要顯示的信息。
這樣就完成了ajax異步局部刷新。
相關文章
相關標籤/搜索