WKWebView 使用示例

WKWebView 新特性

加載 web 頁面

加載本地資源

  • - loadHTMLString:baseURL:
    同步方式加載本地資源,數(shù)據(jù)可以來源于本地文件或者硬編碼的 HTML 字符串
// 設(shè)定主頁文件的基本路徑,通過一個(gè)HTML字符串加載主頁數(shù)據(jù)
- (IBAction)loadHTMLString:(id)sender {
    
    // 主頁文件名
    NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"Baidu001"
                 ofType:@"html"];
    // 主頁文件的基本路徑
    NSURL *bundleUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    
    // 將 index.html 文件的內(nèi)容讀取到 NSString 對象中
    NSError *error = nil;  
    NSString *html = [[NSString alloc] initWithContentsOfFile:htmlPath
                                                     encoding:NSUTF8StringEncoding
                                                        error:&error];
    //數(shù)據(jù)加載沒有錯(cuò)誤的情況下
    if (error == nil) {
        [self.webView loadHTMLString:html baseURL:bundleUrl];
    } 
}
  • - loadData:MIMEType:characterEncodingName:baseURL:
    指定 MIME 類型、編碼集和 NSDate 對象加載一個(gè)主頁數(shù)據(jù),并設(shè)定主頁文件基本路徑
// NSData 是一種二進(jìn)制的字節(jié)數(shù)組類型。它沒有字符集的概念,但用它來裝載 webView 的時(shí)候必須指定字符集。
- (IBAction)loadDATA:(id)sender {
    
    NSString *htmlPath = [[NSBundle mainBundle] pathForResource:@"index"
                 ofType:@"html"];
    NSData *htmlData = [[NSData alloc] initWithContentsOfFile:htmlPath];
  
    NSURL *bundleUrl = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    
    [self.webView loadData:htmlData
                  MIMEType:@"text/html"
          textEncodingName:@"UTF-8"
                   baseURL:bundleUrl];
    
}
  1. 加載本地HTML:iOS9以上的系統(tǒng)可以使用 WKWebView loadFileURL:allowingReadAccessToURL:,iOS9以下的版本沒有這個(gè)方法,需要先將本地HTML文件的復(fù)制到tmp目錄中,然后使用 loadRequest: 方法來加載。如果在HTML中引入其他資源文件,例如js,css,image等必須一同復(fù)制到temp目錄中

    ——WKWebview開發(fā)筆記 @Qin's Blog

加載網(wǎng)絡(luò)資源

// 創(chuàng)建 WKWebView 對象
CGRect rect = CGRectMake(0, 0, self.view.width, self.view.height);
WKWebView *webView = [[WKWebView alloc] initWithFrame:rect];
// 設(shè)置導(dǎo)航代理,監(jiān)聽網(wǎng)頁加載進(jìn)程
_webView.navigationDelegate = self;
// 將 webView 對象添加到視圖
[self.view addSubview:webView];
// 根據(jù)URL發(fā)起網(wǎng)絡(luò)請求
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"www.google.com"]];
[webView loadRequest:request];

創(chuàng)建可與 JavaScript 交互的 WKWebView

1. Objective-C 調(diào)用 JavaScript 方法

  • JS 方法:

    <!-- JavaScript 方法, 接收一個(gè)參數(shù) --> 
    function alertAction(message) {
      alert(message);
    }
    
  • Objective-C 原生調(diào)用

    // OC 調(diào)用 JS 的方法
    [self.mainWebView evaluateJavaScript:@"alertAction('OC調(diào)用JS方法時(shí)傳入的參數(shù)')" completionHandler:^(id _Nullable item, NSError * _Nullable error) {
        NSLog(@"alert");
    }];
    

2. JavaScript 調(diào)用 Objective-C 方法

參考:WKWebView的使用和各種坑的解決方法(OC+Swift)

  • 第一步:
- (WKWebViewConfiguration *)webViewConfiguration {
    if (!_webViewConfiguration) {
        
        // 創(chuàng)建 WKWebViewConfiguration 對象
        _webViewConfiguration = [[WKWebViewConfiguration alloc] init];
        
        // 創(chuàng)建 WKUserContentController 對象,提供 JavaScript 向 webView 發(fā)送消息的方法
        WKUserContentController *userContentColtroller = [[WKUserContentController alloc] init];
        // 添加消息處理,注意:self指代的對象需要遵守 WKScriptMessageHandler 協(xié)議,結(jié)束時(shí)需要移除
        [userContentColtroller addScriptMessageHandler:self name:@"close"];
        // 將 userConttentController 設(shè)置到配置文件
        _webViewConfiguration.userContentController = userContentColtroller;
        
    }
    return _webViewConfiguration;
}

?? ScriptMessageHandler 的 name 必須和 web 中的 JavaScript 方法名稱一致:
window.webkit.messageHandlers.close.postMessage("message");

<script type="text/javascript">

    function doPrint() {
        if (checkiOS() == true) {
            // iOS 注入代碼
            window.webkit.messageHandlers.scriptName.postMessage("script message!");
        } else {
            // Android 注入代碼
            Android.startLHYL();
        }
    }

    // Android/iOS設(shè)備判斷
    function checkiOS() {

        var u = navigator.userAgent;

        var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; // Android
        var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);             // iOS

        if (isiOS) {
            return true;
        } else {
            return false;
        }
    }

</script>
  • 第二步:
#pragma mark - WKScriptMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {

    NSLog(@"%s",__FUNCTION__);
    
    if ([message.name isEqualToString:@"close"]) {
        
        NSLog(@"WKScriptMessage:%@",message.body);
    }
}
  • 第三步:
- (void)dealloc { 
  
    // 移除 ScriptMessageHandler
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"close"];
}

顯示加載進(jìn)度條

對于 WKWebView ,有三個(gè)屬性支持 KVO,因此我們可以監(jiān)聽其值的變化,分別是:loadingtitleestimatedProgress,對應(yīng)功能表示為:是否正在加載中、頁面的標(biāo)題、頁面內(nèi)容加載進(jìn)度(值為0.0~1.0)

剛開始用的方法:WKWebView添加進(jìn)度條 ,參照著寫完發(fā)現(xiàn)如果網(wǎng)速好的話,會出現(xiàn)進(jìn)度條走不完就被隱藏的現(xiàn)象。
解決方法:添加延時(shí)animation動畫,參考:iOS WKWebView添加網(wǎng)頁加載進(jìn)度條

代碼如下:

#import "OSCViewController.h"
#import <WebKit/WebKit.h>

@interface OSCViewController () <WKNavigationDelegate>

@property (nonatomic, strong) NSURL *URL;
@property (nonatomic, strong) WKWebViewConfiguration *webViewConfiguration;
@property (nonatomic, strong) WKWebView *webView;

/** 1?? 添加 progressView 屬性*/
@property (nonatomic, strong) UIProgressView *progressView;

@end

@implementation OSCViewController

#pragma mark - Lifecycle

- (void)loadView {
    [super loadView];
    self.view = self.webView;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // 3?? 將 progressView 添加到父視圖
    [self.view addSubview:self.progressView];

    // 4?? 使用 KVO 注冊觀察者
    // 監(jiān)聽 WKWebView 對象的 estimatedProgress 屬性,就是當(dāng)前網(wǎng)頁加載的進(jìn)度
    [self.webView addObserver:self
                   forKeyPath:@"estimatedProgress"
                      options:NSKeyValueObservingOptionNew
                      context:nil];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:self.URL];
    [self.webView loadRequest:request];
}

- (void)dealloc {
    // 6?? 移除觀察者
    [self.view removeObserver:self forKeyPath:@"estimatedProgress"];

}
#pragma mark - Custom Accessors

- (NSURL *)URL {
    if (!_URL) {
        _URL = [NSURL URLWithString:@"http://www.oschina.net/"];
    }
    return _URL;
}

- (WKWebViewConfiguration *)webViewConfiguration {
    if (!_webViewConfiguration) {
        _webViewConfiguration = [[WKWebViewConfiguration alloc] init];
    }
    return _webViewConfiguration;
}

- (WKWebView *)webView {
    if (!_webView) {
        _webView = [[WKWebView alloc] initWithFrame:[[UIScreen mainScreen] bounds] configuration:self.webViewConfiguration];
        // 設(shè)置導(dǎo)航代理,監(jiān)聽網(wǎng)頁加載進(jìn)程
        _webView.navigationDelegate = self;
    }
    return _webView;
}

/**
 2?? 初始化progressView

 @return 返回初始化后的進(jìn)度條視圖
 */
- (UIProgressView *)progressView {
    if (!_progressView) {
        CGRect sreenBounds = [[UIScreen mainScreen] bounds];
        CGRect progressViewFrame = CGRectMake(0, 64, sreenBounds.size.width, 1);
        _progressView = [[UIProgressView alloc] initWithFrame:progressViewFrame];
        // 設(shè)置進(jìn)度條色調(diào)
        _progressView.tintColor = [UIColor blueColor];
        // 設(shè)置進(jìn)度條跟蹤色調(diào)
        _progressView.trackTintColor = [UIColor whiteColor];
    }
    return _progressView;
}

#pragma mark - KVO

// 5?? 接收變更后的通知,計(jì)算 webView 的進(jìn)度條
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context {
    
    if ([keyPath isEqualToString:@"estimatedProgress"]) {

        self.progressView.progress = self.webView.estimatedProgress;
        
        if (self.progressView.progress == 1) {
            /*
             * 添加一個(gè)簡單的動畫,將 progressView 的 Height 變?yōu)?.5倍
             * 動畫時(shí)長0.25s,延時(shí)0.3s后開始動畫
             * 動畫結(jié)束后將 progressView 隱藏
             */
            __weak __typeof(self)weakSelf = self;
            [UIView animateWithDuration:0.25f delay:0.3f options:UIViewAnimationOptionCurveEaseInOut animations:^{
                weakSelf.progressView.transform = CGAffineTransformMakeScale(1.0f, 1.5f);
            } completion:^(BOOL finished) {
                weakSelf.progressView.hidden = YES;
            }];
        }
        
    }else {
        [super observeValueForKeyPath:keyPath
                             ofObject:object
                               change:change
                              context:context];
    }
}

#pragma mark - WKNavigationDelegate

//  頁面開始加載web內(nèi)容時(shí)調(diào)用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    self.progressView.hidden = NO;
    // 防止 progressView 被網(wǎng)頁擋住
    [self.view bringSubviewToFront:self.progressView];
}

//  當(dāng)web內(nèi)容開始返回時(shí)調(diào)用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    
}

//  頁面加載完成之后調(diào)用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    
}

//  頁面加載失敗時(shí)調(diào)用 ( 【web視圖加載內(nèi)容時(shí)】發(fā)生錯(cuò)誤)
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"Error:%@",error.localizedDescription);
    self.progressView.hidden = YES;
}

// 【web視圖導(dǎo)航過程中發(fā)生錯(cuò)誤】時(shí)調(diào)用。
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
    NSLog(@"Error:%@",error.localizedDescription);
    self.progressView.hidden = YES;

    // 如果請求被取消
    if (error.code == NSURLErrorCancelled) {
        return;
    }
}

// 當(dāng)Web視圖的Web內(nèi)容進(jìn)程終止時(shí)調(diào)用。
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    self.progressView.hidden = YES;
}

@end

監(jiān)聽 webView 的 title 屬性以動態(tài)設(shè)置標(biāo)題

- (void)viewDidLoad {
    [super viewDidLoad];
        
    // 添加觀察者,監(jiān)聽 WKWebView 對象的 title 屬性
    [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:NULL];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:self.URL];
    [self.webView loadRequest:request];
}

- (void)dealloc {
    // 移除觀察者
    [self.view removeObserver:self forKeyPath:@"title"];
}

#pragma mark - KVO

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary<NSKeyValueChangeKey,id> *)change
                       context:(void *)context {
    
     if ([keyPath isEqualToString:@"title"]) {
        self.title = change[@"new"];
    }else {
        [super observeValueForKeyPath:keyPath
                             ofObject:object
                               change:change
                              context:context];
    }
}

URL 中文處理

- (NSURL *)URL {
    if (!_URL) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
        _URL = [NSURL URLWithString:(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)@"https://www.oschina.net/ios/home", (CFStringRef)@"!$&'()*+,-./:;=?@_~%#[]", NULL,kCFStringEncodingUTF8))];
#pragma clang diagnostic pop
    }
    return _URL;
}

導(dǎo)航欄右側(cè)添加刷新按鈕

#pragma mark - Lifecycle

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 刷新按鈕
    UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(rightBarButtonDidClicked:)];
    self.navigationItem.rightBarButtonItem = rightBarButtonItem;
}

#pragma mark - IBActions

- (void)rightBarButtonDidClicked:(id)sender {
    [self.webView reload];
}

禁用長按選中文字效果

https://segmentfault.com/q/1010000006649503
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
    
    // 禁用選中效果
    [self.webView evaluateJavaScript:@"document.documentElement.style.webkitUserSelect='none'" completionHandler:nil];
    [self.webView evaluateJavaScript:@"document.documentElement.style.webkitTouchCallout='none'" completionHandler:nil];
}

加載 HTML 圖片大小自適應(yīng)

參考 WebView加載HTML圖片大小自適應(yīng)與文章自動換行

在 HTML 代碼中設(shè)置內(nèi)容樣式,一般使用 css 或者 js ,根據(jù)加載優(yōu)先級以及加載效果,可以自行選擇。

  • js在頁面加載完之后加載,所以設(shè)置圖片樣式的時(shí)候,會先加載大圖,然后突然變小;
  • css在引入時(shí)加載,直接加載縮小的圖片(實(shí)際占用內(nèi)存不會縮小);

一:使用 CSS 進(jìn)行圖片的自適應(yīng)

#define HTML_NO_HEAD @"![](http://upload-images.jianshu.io/upload_images/2648731-a7ddbb6f227eb44d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br/>![](http://upload-images.jianshu.io/upload_images/2648731-f4855a77d3daa14f.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br/>"

#define HTML_HAD_HEAD @"<head></head><body>![](http://upload-images.jianshu.io/upload_images/2648731-a7ddbb6f227eb44d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br/>![](http://upload-images.jianshu.io/upload_images/2648731-f4855a77d3daa14f.jpeg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)<br/></body>"

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 沒有<head>標(biāo)簽
//    [self.webView loadHTMLString:[self reSizeImageWithHTMLNoHead:HTML_NO_HEAD] baseURL:nil];
    
    // 有<head>標(biāo)簽
    [self.webView loadHTMLString:[self reSizeImageWithHTMLHadHead:HTML_HAD_HEAD] baseURL:nil];
}

/   ----------------------------------------------------------------
// 1.圖片樣式:不管用戶以前設(shè)置的圖片尺寸是多大,都縮放到寬度為320px大小。

// 如果后臺返回的HTML代碼中,不包含 <head> 標(biāo)簽,則可以直接在HTML字符串前拼接代碼。
- (NSString *)reSizeImageWithHTMLNoHead:(NSString *)html {
    
    return [NSString stringWithFormat:@"<head><style>img{width:320px !important;}</style></head>%@", html];
}

// 如果包含 <head> 標(biāo)簽,則在<head>標(biāo)簽內(nèi)部替換添加
- (NSString *)reSizeImageWithHTMLHadHead:(NSString *)html {
    
    return [HTML_HAD_HEAD stringByReplacingOccurrencesOfString:@"<head>" withString:@"<head><style>img{width:320px !important;}</style>"];
}

/   ----------------------------------------------------------------
// 2.圖片樣式:若需要根據(jù)圖片原本大小,寬度小于320px的不縮放,大于320px的縮小到320px,那么在HTML字符串前加上一下代碼:
- (NSString *)reSizeImageWithHTML:(NSString *)html {
    
    return [NSString stringWithFormat:@"<head><style>img{max-width:320px !important;}</style></head>%@", html];
}

二:使用 JavaScript 進(jìn)行圖片的自適應(yīng)

在 webview 的代理中,執(zhí)行 JavaScript 代碼。(下面這段代碼是必須有 <head> 標(biāo)簽的)

如果沒有 <head> 標(biāo)簽,也很簡單,只需要給返回的 HTML 字符串前面拼接一個(gè) <head></head> 即可。

- (void)webViewDidFinishLoad:(UIWebView *)webView
 {
    [webView stringByEvaluatingJavaScriptFromString:
     @"var script = document.createElement('script');"
     "script.type = 'text/javascript';"
     "script.text = \"function ResizeImages() { "
         "var myimg,oldwidth,oldheight;"
         "var maxwidth=320;"http:// 圖片寬度
         "for(i=0;i <document.images.length;i++){" "myimg = document.images[i];" "if(myimg.width > maxwidth){"
                 "myimg.width = maxwidth;"
             "}"
         "}"
     "}\";"
     "document.getElementsByTagName('head')[0].appendChild(script);"];
    [webView stringByEvaluatingJavaScriptFromString:@"ResizeImages();"];
}

文章內(nèi)容自動換行

文章的自動換行也是通過css實(shí)現(xiàn)的,書寫方式圖片縮放類似。在沒有<body>標(biāo)簽的情況下,在HTML代碼前,直接拼接以下代碼即可(若包含<body>,則將代碼添加到body標(biāo)簽內(nèi)部),意思是全部內(nèi)容自動換行。

<body width=320px style=\"word-wrap:break-word; font-family:Arial\">

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,935評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,908評論 2 372

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