SAPUI5 (13) - 數(shù)據(jù)綁定之聚合綁定(aggregation binding)

上次我們介紹了屬性綁定的妖。屬性綁定用于綁定單條數(shù)據(jù)绣檬。如果需要綁定多條數(shù)據(jù),則需要使用聚合綁定(aggregation binding)嫂粟,比如我們常見的ListBox, Combox或者表格娇未,都是含有多條數(shù)據(jù)的。概念比較容易理解星虹,關(guān)鍵是綁定的語法零抬。如果所有行都用同樣的方法顯示數(shù)據(jù),用template方法宽涌。什么是template方法呢平夜?就是各行的數(shù)據(jù)顯示方式應(yīng)該是固定的,像套用模板一樣卸亮。比如顯示供應(yīng)商信息忽妒,每一行的第一列是供應(yīng)商ID,第二列是供應(yīng)商名稱,都是固定的段直。熟悉ABAP的語言的讀者吃溅,可以根據(jù)ABAP內(nèi)表的line type來理解。

我們在前面用sap.ui.table.Table顯示供應(yīng)商數(shù)據(jù)的時(shí)候坷牛,已經(jīng)有相應(yīng)的例子罕偎,請參考:SAPUI5 (08) - MVC的Model和數(shù)據(jù)綁定。 Template方式綁定有以下幾種方式:

  1. 使用settings設(shè)置
  2. 使用sap.ui.base.ManagedObjectbindAggregation()方法
  3. 使用控件的類型化綁定方法

這三種方法本篇都會(huì)介紹京闰。如果想各行綁定的數(shù)據(jù)有變化,或者說是動(dòng)態(tài)的甩苛。比如在一個(gè)表格中蹂楣,有一列顯示讀者對某文章的點(diǎn)擊次數(shù),當(dāng)點(diǎn)擊次數(shù)超過100時(shí)讯蒲,除了點(diǎn)擊次數(shù)痊土,還顯示熱門標(biāo)記,則可以使用factory function的方式來綁定墨林。后面也會(huì)給出示例赁酝。

本次使用sap.m.Table控件顯示數(shù)據(jù),所以先介紹下sap.m.Table的一些語法要點(diǎn)旭等。

sap.m.Table

sap.m.Table
control provides a set of sophisticated and convenience functions for responsive table design. To render the sap.m.Table properly, the order of the columns aggregation should match with the order of the items cells aggregation. Also sap.m.Table requires at least one visible sap.m.Column in columnsaggregation. For mobile devices, the recommended limit of table rows is 100 (based on 4 columns) to assure proper performance. To improve initial rendering on large tables, use the growing feature.
查看

sap.m.Tablesap.m.ListBase類繼承酌呆,用于顯示包含行和列的表格式數(shù)據(jù)。表格的列可以通過columns聚合屬性來設(shè)置搔耕,也可以使用addColumn()方法來添加隙袁。每一列都是sap.m.Column對象。至少包含一個(gè)可見列弃榨。在一定設(shè)備上不要加載太多行菩收,以免影響性能。

sap.m.Table的重要屬性:

  • columns: 定義Table包含哪些列鲸睛,類型是sap.m.Column數(shù)組娜饵。

另外,sap.m.Tablesap.m.ListBase繼承官辈,所以可以直接使用sap.m.ListBase的屬性:

  • growing: 設(shè)置Table顯示的數(shù)據(jù)可以依據(jù)向model的請求增加行
  • noDataText: 當(dāng)Table沒有數(shù)據(jù)的時(shí)候顯示的文本箱舞,類型是string
  • items: sap.m.ListItemBase數(shù)組,sap.m.ListItemBase類定義了列表項(xiàng)(list item)的基本特征钧萍。

sap.m.ColumnListItem

使用template方法顯示數(shù)據(jù)褐缠,每一行的template常用sap.m.ColumnListItem,所以接下來介紹sap.m.ColumnListItem的知識(shí)點(diǎn):

sap.m.ColumnListItem can be used with the cells aggregation to create rows for the sap.m.Table control. The columns aggregation of the sap.m.Table should match with the cells aggregation.
查看

sap.m.ColumnListItem用于創(chuàng)建sap.m.Table的行风瘦,行中包含的cells需要與sap.m.Table的Columns匹配队魏,順序一致。

本次將用到以下屬性:

  • vAlign, 行的垂直對齊:

    • sap.ui.core.VerticalAlign.Bottom胡桨,底部對齊
    • sap.ui.core.VerticalAlign.Inherit官帘,從父控件繼承
    • [sap.ui.core.VerticalAlign.Middle, 居中對齊
    • sap.ui.core.VerticalAlign.Top,頂部對齊
  • cells: 行包含的cells昧谊,每一個(gè)cell都是sap.ui.core.Control對象刽虹,從而開發(fā)人員可以根據(jù)需要選擇合適的控件,靈活度很高呢诬。

聚合綁定示例

和之前一樣涌哲,通過例子來加強(qiáng)理解。今天要實(shí)現(xiàn)的業(yè)務(wù)場景是在頁面中顯示一個(gè)文章列表尚镰,這些文章的閱讀次數(shù)阀圾,我們的要顯示的界面如下:

為了便于理解,先給出application area的完整代碼:

/**
 * Aggregation binding
 * Demo written by Stone Wang
 */

// application data
var oAppData = [
    { articleName: "SAP成本計(jì)算流程", type: "Locked", hits: 1048 },
    { articleName: "SAP物料價(jià)格修改", type: "Draft", hits: 58 },
    { articleName: "2017年SAP技術(shù)趨勢", type: "Unsaved", hits: 320},
    { articleName: "《人類簡史》讀后感", type: "Flagged", hits: 90 },
    { articleName: "《Core Java》第十版出版", type: "Favorite" , hits: 66}
];

var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({ modelData: oAppData });

sap.ui.getCore().setModel(oModel);

// 定義一個(gè)包含包含3列的數(shù)組
var aColumns = [
    new sap.m.Column({
        header : new sap.m.Label({text : "文章"})
    }),     
    new sap.m.Column({
        header : new sap.m.Label({text : "標(biāo)記"})
    }),
    new sap.m.Column({
        header : new sap.m.Label({text : "標(biāo)記"})
    })
]

// 定義template, 每行包含3個(gè)cell
var oColumnListItem = new sap.m.ColumnListItem({
    vAlign: "Middle",
    cells: [
        new sap.m.Text({text: "{articleName}"}),
        new sap.m.ObjectMarker({type: "{type}"}),
        new sap.m.ObjectMarker({
            type: "{type}",
            active: true,
            press: function(oEvent){
                sap.m.MessageToast.show(oEvent.getParameter("type") + " pressed");
            }
        })   
    ]
});


// Table control
var oTable = new sap.m.Table({
    columns : aColumns,
    items: {path: "/modelData", template: oColumnListItem}
});

var oTablePanel = new sap.m.Panel({
    headerText: "文章列表",
    content: oTable
});

var oStandalonePanel = new sap.m.Panel("standalone-panel", {
    headerText: "圖例:",
    content: [
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Locked}),      
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Flagged}),
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Favorite}),            
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Draft}),       
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Unsaved})
    ]
});

var oApp = new sap.m.App({  initialPage: "page" });
var oPage = new sap.m.Page("page", {
    title:"Aggregation binding demo",
    content: [oTablePanel, oStandalonePanel]
});
oApp.addPage(oPage).placeAt("content");

我們說明最主要的部分狗唉。因?yàn)門able包含三列初烘,所以我們先定義一個(gè)包含3列的數(shù)組,每一列都是sap.m.Column對象分俯。

// 定義一個(gè)包含包含3列的數(shù)組
var aColumns = [
    new sap.m.Column({
        header : new sap.m.Label({text : "文章"})
    }),     
    new sap.m.Column({
        header : new sap.m.Label({text : "標(biāo)記"})
    }),
    new sap.m.Column({
        header : new sap.m.Label({text : "標(biāo)記"})
    })
]

剛才說過肾筐,對于每一行來說,都是一個(gè)template缸剪,我們使用ColumnListItem來代表template吗铐,每一行包含三個(gè)單元格,使用cells屬性表示橄登。每一個(gè)cell都是Control對象抓歼,我們使用sap.m.Text顯示第一個(gè)單元格,綁定到articleName拢锹,使用sap.m.ObjectMarker顯示第二個(gè)單元格和第三個(gè)單元格谣妻,第三個(gè)單元格與event handler綁定:

// 定義template, 每行包含3個(gè)cell
var oColumnListItem = new sap.m.ColumnListItem({
    vAlign: "Middle",
    cells: [
        new sap.m.Text({text: "{articleName}"}),
        new sap.m.ObjectMarker({type: "{type}"}),
        new sap.m.ObjectMarker({
            type: "{type}",
            active: true,
            press: function(oEvent){
                sap.m.MessageToast.show(oEvent.getParameter("type") + " pressed");
            }
        })   
    ]
});

最后定義sap.m.Table對象,使用columns聚合屬性和items聚合屬性卒稳,items屬性實(shí)現(xiàn)的就是聚合綁定蹋半,當(dāng)然,需要ColumnListItem的支持充坑。

// Table control
var oTable = new sap.m.Table({
    columns : aColumns,
    items: {path: "/modelData", template: oColumnListItem}
});

對Table的綁定减江,我們也可以使用bingItems方法來實(shí)現(xiàn):

var oTable = new sap.m.Table({
    columns: aColumns
});
oTable.bindItems("/modelData", oColumnListItem);

或者:

var oTable = new sap.m.Table({
    columns: aColumns
});
oTable.bindAggregation("items", "/modelData", oColumnListItem);

使用工廠函數(shù)實(shí)現(xiàn)聚合綁定

對上面的例子進(jìn)行重構(gòu),假設(shè)我們想顯示這些文章的閱讀次數(shù)捻爷,并且當(dāng)閱讀次數(shù)超過100時(shí)辈灼,就在閱讀次數(shù)下面加一個(gè)”熱門”字眼來標(biāo)識(shí)。也就是不同的單元格在顯示的時(shí)候是動(dòng)態(tài)的也榄。對這種動(dòng)態(tài)的數(shù)據(jù)顯示巡莹,就需要用factory function司志。如何做呢?我們使用sap.m.TablebindAggregation()方法降宅,參數(shù)3使用匿名函數(shù)骂远,這個(gè)函數(shù)就是factory function:

// 使用Factory function實(shí)現(xiàn)動(dòng)態(tài)的數(shù)據(jù)顯示
oTable.bindAggregation("items", "/modelData", function(sId, oContext){
    var oColumnListItem = new sap.m.ColumnListItem(sId, {vAlign: "Middle"});
    oColumnListItem.addCell(new sap.m.Text({text: "{articleName}"}));
    oColumnListItem.addCell(new sap.m.ObjectMarker({type: "{type}"}));
    
    var oHits = oContext.getProperty("hits");   
    if (oHits >= 100) {
        oColumnListItem.addCell(
            new sap.ui.layout.VerticalLayout({
                content: [
                   new sap.m.Text({text: "{hits}"}),
                   new sap.m.ObjectStatus({text:"熱門", state:"Success"})
                ]
            })
        )
    } else {
        oColumnListItem.addCell(
            new sap.m.Text({text: "{hits}"})
        )       
    }
    
    return oColumnListItem;
});

注意Facotry 函數(shù)的參數(shù)必須是sId和oContext。如果點(diǎn)擊次數(shù)大于或等于100腰根,則cell中包括一個(gè)sap.m.Text和一個(gè)sap.m.ObjectStatus對象激才,垂直布局。如果點(diǎn)擊次數(shù)小于100额嘿,則只有一個(gè)sap.m.Text來顯示瘸恼。函數(shù)最后需要使用return語句返回sap.m.ColumnListItem對象。

貼上完整代碼:

/**
 * Aggregation binding using factory function
 * Demo written by Stone Wang
 */

// application data
var oAppData = [
    { articleName: "SAP成本計(jì)算流程", type: "Locked", hits: 1048 },
    { articleName: "SAP物料價(jià)格修改", type: "Draft", hits: 58 },
    { articleName: "2017年SAP技術(shù)方向", type: "Unsaved", hits: 320},
    { articleName: "《人類簡史》讀后感", type: "Flagged", hits: 90 },
    { articleName: "《Core Java》第十版出版", type: "Favorite" , hits: 66}
];

var oModel = new sap.ui.model.json.JSONModel();
oModel.setData({ modelData: oAppData });

sap.ui.getCore().setModel(oModel);

// 定義Column數(shù)組册养,包含3列
var aColumns = [
    new sap.m.Column({
        header : new sap.m.Label({text : "文章"})
    }),     
    new sap.m.Column({
        header : new sap.m.Label({text : "標(biāo)記"})
    }),
    new sap.m.Column({
        header : new sap.m.Label({text: "閱讀次數(shù)"})
    })
    ]


// Table control
var oTable = new sap.m.Table({
    columns : aColumns  
});


// 使用Factory function實(shí)現(xiàn)動(dòng)態(tài)的數(shù)據(jù)顯示
oTable.bindAggregation("items", "/modelData", function(sId, oContext){
    var oColumnListItem = new sap.m.ColumnListItem(sId, {vAlign: "Middle"});
    oColumnListItem.addCell(new sap.m.Text({text: "{articleName}"}));
    oColumnListItem.addCell(new sap.m.ObjectMarker({type: "{type}"}));
    
    var oHits = oContext.getProperty("hits");   
    if (oHits >= 100) {
        oColumnListItem.addCell(
            new sap.ui.layout.VerticalLayout({
                content: [
                   new sap.m.Text({text: "{hits}"}),
                   new sap.m.ObjectStatus({text:"熱門", state:"Success"})
                ]
            })
        )
    } else {
        oColumnListItem.addCell(
            new sap.m.Text({text: "{hits}"})
        )       
    }
    
    return oColumnListItem;
});


var oTablePanel = new sap.m.Panel({
    headerText: "文章列表",
    content: oTable
});

var oStandalonePanel = new sap.m.Panel("standalone-panel", {
    headerText: "圖例:",
    content: [
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Locked}),      
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Flagged}),
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Favorite}),            
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Draft}),       
        new sap.m.ObjectMarker({type: sap.m.ObjectMarkerType.Unsaved})
    ]
});

var oApp = new sap.m.App({  initialPage: "page" });
var oPage = new sap.m.Page("page", {
    title:"Aggregation binding demo",
    content: [oTablePanel, oStandalonePanel]
});
oApp.addPage(oPage).placeAt("content");

頁面顯示效果如下:

用xmlview實(shí)現(xiàn)factory方法的聚合綁定

xmlview是聲明式的钞脂,factory方式的聚合綁定卻是為了實(shí)現(xiàn)動(dòng)態(tài)的顯示。那么捕儒,如何在xmlview中實(shí)現(xiàn)動(dòng)態(tài)呢?要點(diǎn)如下:
1)xmlview中對需要?jiǎng)討B(tài)顯示的部分不作聲明
2)在controller中定義factory function邓夕,實(shí)現(xiàn)控件的綁定和動(dòng)態(tài)加載刘莹。

仍然用剛才的例子進(jìn)行重構(gòu),項(xiàng)目文件和路徑如下:

將數(shù)據(jù)放在json文件articles.json中焚刚,內(nèi)容:

[
    { "articleName": "SAP成本計(jì)算流程", "type": "Locked", "hits": 1048 },
    { "articleName": "SAP物料價(jià)格修改", "type": "Draft", "hits": 58 },
    { "articleName": "2017年SAP技術(shù)方向", "type": "Unsaved", "hits": 320},
    { "articleName": "《人類簡史》讀后感", "type": "Flagged", "hits": 90 },
    { "articleName": "《Core Java》第十版出版", "type": "Favorite" , "hits": 66}
]

index.html只有oAppoView点弯,oApp`放在DIV中。

<!DOCTYPE HTML>
<html>
    <head>
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>

        <script src="resources/sap-ui-core.js"
                id="sap-ui-bootstrap"
                data-sap-ui-libs="sap.m, sap.ui.layout"
                data-sap-ui-resourceroots='{"bindingtest": "./binding_test"}'
                data-sap-ui-theme="sap_bluecrystal">
        </script>

        <script>            
            var oApp = new sap.m.App({initialPage: "mainpage"});
            var oView = sap.ui.xmlview({
                id: "mainpage",
                viewName: "bindingtest.view.aggregation_binding"
            });
    
            oApp.addPage(oView);
            oApp.placeAt("content");
        </script>

    </head>
    <body class="sapUiBody" role="application">
        <div id="content"></div>
    </body>
</html>

aggregation_binding.view.xml:

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" 
           xmlns="sap.m"
           controllerName="bindingtest.controller.aggregation_binding" 
           xmlns:html="http://www.w3.org/1999/xhtml">

    <Panel class="sapUiSmallMargin" headerText="文章列表">
        <content>
            <Table id="table" width="auto" class="sapUiSmallMargin"
                noDataText="no data">
                <columns>
                    <Column><header><Label text="文章" /></header></Column>
                    <Column><header><Label text="標(biāo)記" /></header></Column>
                    <Column hAlign="Right"><header><Label text="閱讀次數(shù)" /></header></Column>                  
                </columns>
            </Table>
        </content>
    </Panel>
    
    <Panel class="sapUiSmallMargin" headerText="圖例">
        <content>
            <ObjectMarker class="sapUiSmallMargin" type="Locked" />
            <ObjectMarker class="sapUiSmallMargin" type="Flagged" />
            <ObjectMarker class="sapUiSmallMargin" type="Favorite" />
            <ObjectMarker class="sapUiSmallMargin" type="Draft" />
            <ObjectMarker class="sapUiSmallMargin" type="Unsaved" />
        </content>
    </Panel>
</core:View>

注意sap.m.Table只聲明了columns矿咕,沒有聲明items抢肛。items在代碼中實(shí)現(xiàn)。

aggregation_binding.controller.js

sap.ui.define(["sap/ui/core/mvc/Controller"], 
    function(Controller){
        "use strict";
        
        // controller name
        return Controller.extend("bindingtest.controller.aggregation_binding", {
            
            //-------------------------------
            // initialization
            //-------------------------------
            onInit: function() {
                // binding view with model
                var oModel = sap.ui.model.json.JSONModel();
                oModel.loadData('binding_test/model/articles.json');
                this.getView().setModel(oModel);
                
                // Table object add items
                var oTable = this.getView().byId("table");
                oTable.bindItems({path: '/', factory: this.createCellsFactory});
            },
            
            //------------------------------------------------
            // Factory function to add cells for table
            //------------------------------------------------
            createCellsFactory: function(sId, oContext) {       
            
                var oColumnListItem = new sap.m.ColumnListItem(sId, {vAlign: "Middle"});
                
                // first two cells are not dynamic
                oColumnListItem.addCell(new sap.m.Text({text: "{articleName}"}));
                oColumnListItem.addCell(new sap.m.ObjectMarker({type: "{type}"}));      
                
                // third cell is dynamic
                var oHits = oContext.getProperty("hits");   
                if (oHits >= 100) {
                    oColumnListItem.addCell(
                        new sap.ui.layout.VerticalLayout({
                            content: [
                               new sap.m.Text({text: "{hits}"}),
                               new sap.m.ObjectStatus({text:"熱門", state:"Success"})
                            ]
                        })
                    )
                } else {
                    oColumnListItem.addCell(
                        new sap.m.Text({text: "{hits}"})
                    )       
                }
        
                return oColumnListItem;
            } // end of createCellsFactory()            
            
        });
    }
);

在onInit()中調(diào)用oTable的bindItems方法碳柱,bindItems方法包含factory方法: oTable.bindItems({path: '/', factory: this.createCellsFactory});

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捡絮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子莲镣,更是在濱河造成了極大的恐慌福稳,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瑞侮,死亡現(xiàn)場離奇詭異的圆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)半火,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門越妈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人钮糖,你說我怎么就攤上這事梅掠。” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵瓤檐,是天一觀的道長赂韵。 經(jīng)常有香客問我,道長挠蛉,這世上最難降的妖魔是什么祭示? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮谴古,結(jié)果婚禮上质涛,老公的妹妹穿的比我還像新娘。我一直安慰自己掰担,他們只是感情好汇陆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著带饱,像睡著了一般毡代。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勺疼,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天教寂,我揣著相機(jī)與錄音,去河邊找鬼执庐。 笑死酪耕,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的轨淌。 我是一名探鬼主播迂烁,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼递鹉!你這毒婦竟也來了盟步?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤梳虽,失蹤者是張志新(化名)和其女友劉穎址芯,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體窜觉,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谷炸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禀挫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旬陡。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖语婴,靈堂內(nèi)的尸體忽然破棺而出描孟,到底是詐尸還是另有隱情驶睦,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布匿醒,位于F島的核電站场航,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏廉羔。R本人自食惡果不足惜溉痢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望憋他。 院中可真熱鬧孩饼,春花似錦、人聲如沸竹挡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽揪罕。三九已至梯码,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間好啰,已是汗流浹背忍些。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坎怪,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓廓握,卻偏偏與公主長得像搅窿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子隙券,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容