extjs跨域请求

前后端分离架构离不开跨域请求,ext也不例外,ext封装了jsonp模块,相关的有 jsonpStore 和 jsonpProxy

原理

如果有这个请求

Ext.data.JsonP.request({
    url : 'foo.php'
});

ext会在头部创建一个 script 标签请求 foo.php 路径下的资源(get方法),对应的路径 foo.php?callback=Ext.data.JsonP.callback1 服务器请求获取对应的 callback 参数返回对应的函数执行字符串

Ext.data.JsonP.callback1({"foo":"bar"});

服务器请求处理 

<?php

$data = array('foo' => 'bar');

if (!empty($_REQUEST['callback'])) {
    header('Content-Type: application/javascript');
    echo $_REQUEST['callback'] . '(';
}

echo json_encode($data);

if (!empty($_REQUEST['callback']) {
    echo ');';
}

?>

JsonPStore

JsonpStore和普通的store差不多,请求方式是用上面的原理来请求数据,配置JsonPStore

Ext.define("extjsapp2.store.Question", {
    extend: "Ext.data.JsonPStore",
    alias: "store.question",
    storeId: "questionStore",
    proxy: {
        url: "http://localhost:3000/api/questions"
    },
    fields: ["title"],
    autoLoad: true
})

extjs会生成对应当路径 http://localhost:3000/api/questions?_dc=1496547546379&page=1&start=0&limit=25&callback=Ext.data.JsonP.callback1  请求服务器资源

每次请求附加参数 extraParams

proxy: {
    url: "http://localhost:3000/api/questions",
    extraParams: {
        token: "kalsjdaieroqwnlnlk"
    },
},

自己测试了一遍,返回数据是数组可以正常渲染,但是嵌套子对象设置 root/rootProperty 都无法获取对应点数组,不知道是不是bug

Store + Proxy

上面的不能设置 root 来指定数组渲染数据,用正常的store和proxy来实现jsonp,可以获取嵌套的数据,发现什么问题

Ext.define("extjsapp2.store.Question", {

    extend: "Ext.data.Store",
    alias: "store.question",
    storeId: "questionStore",
    proxy: {
        type: 'jsonp',
        url: "http://localhost:3000/api/questions",
        extraParams: {
            curPage: 1,
            token: "kalsjdaieroqwnlnlk"
        },
        reader: {
            type: 'json',
            rootProperty: 'list',   // 子对象数组
        }
    },
    fields: ["title"],
    autoLoad: true,
    listeners: {
        load: function (store, records, successful, eOpts) {
            console.log(records)
        }
    }
})

jsonp request

在处理程序中请求jsonp数据,例如点击按钮获取

Ext.data.JsonP.request({
    url: 'http://localhost:3000/api/questions',
    callbackKey: 'callback',
    params: {
        key: '23f6a0ab24185952101705',
    },
    success: function(result, request) {
        console.log(result);
    }
});

post跨域请求

跨站请求另一种方式在服务端实现,Cross-Origin Resource Sharing(跨域资源共享)是一种允许当前域(origin)的资源(比如html/js/web service)被其他域(origin)的脚本请求访问的机制。
当使用XMLHttpRequest发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头:origin,后端在接受到请求后确定响应后会在Response Headers中加入一个属性:Access-Control-Allow-Origin,值就是发起请求的源地址(http://127.0.0.1:8888),浏览器得到响应会进行判断Access-Control-Allow-Origin的值是否和当前的地址相同,只有匹配成功后才进行响应处理。

在服务器返回的头部设置 "Access-Control-Allow-Origin":'*' 就可以实现跨域请求

extjs官方推荐的使用jsonp,使用 Ext.Ajax.request 也可以来实现跨域请求

Ext.Ajax.request({
    url: 'http://www.cctv.com/datas',
    timeout: 3000,
    method: "POST",
    cros: true,
    useDefaultXhrHeader: false,
    params: {
        params: JSON.stringify({
            from: 0,
            to: 4294967295
        })
    },
    paramsAsJson: true,
    success: function (data) {}
})