设计实践的九个原则



引子:

        一直觉得,用户体验的设计方法(如系统设计、原子设计等),与前端的很多概念、思考方式是相通的。困惑许久但并没有找到满意的答案——直到偶然发现这篇文章,自觉收获颇多。我的目的,并不是要真正去学习写代码,而是想从用户体验亦或交互设计的思维方法出发,去思考、理解设计付诸实施的过程。我们重视的,不应该是这些看似苛刻的“原则”,更不是具体的代码技巧(对设计师更是如此),而应该是这样的思维体系,它可以被运用在日常工作中,不管是输出设计方案、创建设计规范,亦或是写代码。另一方面,我想看看一些前端思维和工作方法,是否也可以借鉴到我们的设计工作中来。我相信,这些思考,对于使我的设计工作在实践层更合理、高效而具有逻辑大有裨益;同时,也期望能够促进我们在日常工作中与各方更有效率的沟通。

原文中不少些技术概念和名词,对于专业开发来说可能只是入门级常识,但对我这样只懂得一点HTML和CSS皮毛的代码小白来说却有些“深奥”,需要耗费不少精力才能从自己的角度理解。正因如此,有些翻译不可能不够精准。虽尽全力但难免存在诸多不足。但,在翻译中揣摩、推测、反思……自觉这是一个很棒的学习过程。

最近,我在为我们的一个客户开展一项培训课程,关于使用HTML和CSS实现设计的最佳实践。我们的讨论包括诸如“风格指南驱动开发”的流程,OOCSS(面向对象的 CSS)和SMACSS(可伸缩和模块化的CSS)等方法的讨论以及模块化设计。最后一天快要结束时,有人问:“然而,我们怎么知道自己做得对不对?”

起初,我很困惑。我花了数小时的时间告诉他们使事情“做对”的一切方法。但是在思考之后,我意识到这个问题根源在于对指导和评估的深层需求,这些常常是一组主观选择——有时候是在不同的时间由很多不同的人做出的。像一致的命名规范和现场风格指南是最终的结果,但这些“最佳实践”植根于更深层次的价值观,并不总是明确直观的。例如,如果没有对模块化的更广泛的认识,诸如“最小化另一个类与之合作的类的数量”这样的具体建议就没有帮助意义。

我意识到,为了真正了解我们的工作是否有用,我们需要更高层次的原则,可以作为设计执行的衡量标准。我们需要一些与某种特定语言(如CSS)不一样的东西,或一种固执己见的方式来书写它(衡量标准)。就像通用的设计原理或者Nielsen的可用性法则一样,我们需要一些东西来指导我们实现设计的方式,而不必确切地告诉我们如何去做。为实现这一目标,我制定了九个设计执行原则。

创建渐进式的单页面应用程序。

仅仅只需要使用几个CSS技巧、少于0.5 KB大小的JavaScript代码,以及更重要的一些静态HTML,Heydon Pickering为渐进式增强的单页应用程序引入了一个实验性解决方案

这不是一个清单。相反,这是一套广泛的指导方针,对于保持(工作)潜在价值很重要。它可以作为设计执行人员的指南,或作为评估现有项目的工具。因此,无论您是在审核代码,审核CSS还是为团队中的角色面试候选人,这些原则都应该提供一种超越特定技术的结构,并为落实设计引入一种通用的方式。

结构化

文档是语义化的且合乎逻辑的,无论它有或没有样式。

高效的

使用了最少量的标记和资源(指令、过滤器、组件等)来实现设计。

标准化

通用原则被充分地保留和使用。

抽象化

基本元素与特定上下文是分离的,并能形成核心框架。

模块化

通用元素在逻辑上可被分解成可复用的组件。

可配置

通过可选参数来对基本元素进行自定义配置是可行的。

可扩展

该代码很容易扩展,并为未来的优化预留空间。

文档化

所有元素都被有备注以便供他人使用和扩展。

准确的

最终输出能恰当地实现预期设计。

为了便于参照,以及了解每个原理如何应用于一个项目,我们将使用我的一个项目中的设计模型作为本文的基础。这是一个在现有电商网站促进日常交易的特殊登录页面。 虽然一些风格将继承现有的网站,但要重点说明的一点是,这些元素中的大部分都是全新的。 我们的目标是,通过以上原则来将这张静态图片转换成HTML和CSS。


这些“卡片”设计对于我们的电商网站来说是全新的

1、结构化

文档是语义化的且合乎逻辑的,无论它有或没有样式。

这里的原则是,即使没有表现样式(CSS),我们的文档(HTML)内容也应当是有意义的。当然,这意味着我们正在使用正确排序的标题级别和无序列表,还要使用有意义的容器,如和。我们不应该跳过使用诸如ARIA标签、alt属性和其他我们可能需要的东西来获得可访问性。

这看起来可能不是什么大不了的事情,但是不管你使用链接标签还是按钮它都是重要的——即使它们在视觉上都是相同的,因为它们传达不同的含义并提供不同的交互。语义标记将这些含义传达给搜索引擎和辅助技术,甚至可以更轻松地将我们的工作重新应用于其他设备。这使我们的项目更具前瞻性。

创建一个结构良好的文档意味着要学习编写语义化的HTML,并熟悉W3C标准,甚至是其他专家的一些最佳实践,并花时间让代码易于理解。最简单的测试是在浏览器中查看没有样式的HTML:

•没有CSS后它是可用的吗?

•它是否还有可见的层次结构?

•原始的HTML本身是否能表达意义?

确保结构化文档的一个最好的事情就是从HTML开始。在考虑视觉样式之前,请先写出纯文本格式的HTML文档,以此来表达文档结构和每个部分的含义。避免div标签,并考虑一个合适的包裹标签应该是什么样的。只需这个基本步骤,将帮助你创建一个合适的结构。

 

   

Daily Deals

    Sort

   

         

  • by ending time
  •      

  • by price
  •      

  • by popularity

  •    




     

         

    •      

              Ends in 9:42:57

             

      12" Night Therapy Euro Box Top Spring

              $199.99

              List $299

              10 Left

      只从HTML开始,并思考每个元素的含义,可以产生一个更加结构化的文档。从上面的例子,你可以看到我创建了一个完整的标记文档,而没有使用一个div。

      2、高效的

      使用了最少量的标记和资源(指令、过滤器、组件等)来实现设计。

      我们必须考虑我们的代码,以确保它简洁且不包含不必要的标记或样式。对于我来说,使用特定框架的类名来检查嵌套div中的代码是很常见的,这样只是为了实现块级元素的右对齐。 过度使用HTML通常是不了解CSS或底层框架的结果。

      这里有一个常见的过度依赖框架的例子,它会产生臃肿的HTML和CSS,以及无数的div。考虑标记需要什么,而不是为实现预期设计框架可以做什么。这里有一个常见的过度依赖框架的例子,它会产生臃肿的HTML和CSS,以及divitis的情况。 考虑需要什么标记,而不是框架可以做什么来实现所需的设计。

      除了标记和CSS之外,我们还可能需要其他外部资源,例如图标,Web字体和图像。 关于实现这些资源的最佳方法,从自定义图标字体到嵌入base64编码的外部SVG,有许多很棒的方法和意见。 每个项目都是不同的,但是如果你在按钮上使用一个500像素的PNG图标,那么你有可能没有考虑效率。

      这并非仅是文件大小的问题。 在处理外部资源时(如图像或图标字体),考虑在CSS中运用base64编码过的图标,这对编写高效的代码非常重要。

      在评估项目的效率时,有两个重要的问题需要问考虑:

      •我能用更少的代码完成同样的事情吗?

      •优化资源以实现最小负载(smalles overhead)的最佳方法是什么?

      实践中的效率也与接下来的原则——标准化和模块化是一致的(0verlaps),因为高效的一种方法就是使用既定标准来实现设计并使其可重用。 为普通的box阴影创建一个mixin(多重继承)是高效的,因为这同时也创建一个模块化的标准。

      3、标准化

      通用原则被充分地保留和使用。

      为网站或应用程序创建标准,通常需建立规则来管理一些细节,诸如标题级别和大小、常见槽(注:栅格系统中的列间距)宽度以及每种按钮类型样式等。 一般在CSS中,您必须将这些规则保留在外部样式指南中,并记住正确应用它们;但如使用诸如LESS或Sass之类的预处理器是最好的,以便您可以将它们存储在变量和mixins中。 这里的重点是,要重视像素级保真设计的标准。

      所以,当我得到一个22像素宽度的栅格(gutter)设计原型,而不是我们在其他地方使用的15像素时,我将认为这样的精度是不值得的,并会使用标准的15像素的分栏。 更进一步,元素之间的所有间距将使用这个标准的倍数。 另一种动态的间距标准是“$ gutter-width * 2”(等于30像素),而不是写死的一个值。 通过这种方式,整个应用程序将具有一致的,对齐的感觉。

      .product-cards {

        li {

          display: inline-block;

          padding: @gutter-width/4;

          color: @text-color;

          text-decoration: none;

          background-color: @color-white;

          .border;

          margin-bottom: @gutter-width/2;

          margin-right: @gutter-width/2;

        }

      }


      .product-status {

        font-size: @font-size-small;

        color: @grey-darker;

        font-weight: @font-weight-bold;

        margin-bottom: @gutter-width/4;

      }

      因为我们使用了从LESS变量或mixin派生的标准化值,所以我们的CSS本身没有任何数值。一切都从一个集中值(centralized value)继承而来。

      要检查标准化,请查看CSS并查找任何写死的部件:像素,HEX颜色(十六进制),ems或几乎任何数值:

      •这些部件是否应使用现有的标准值或变量?

      •部件是否是重复使用的,以便从新变量中受益?也许你已经意识到,这是你第二次应用了半透明的背景,那么两次都需要使用相同的不透明度。

      •部件是否可以从现有变量的计算中推导出来?这对于颜色的变化非常有用 - 例如,使用标准颜色并对其进行计算以使颜色变暗10%,而不是写死的HEX值。

      我会尽量使用标准的值,只在有特例时才创建新的标准值。如果你发现自己调整了某个元素某处的5个像素和另一处的1个像素,那么很有可能你的标准正在被破坏。

      根据我的经验,大多数预处理的CSS应该使用集中变量和mixins,并且在单个组件中应该几乎看不到数值,像素或HEX值。偶尔,增加几个像素来调整单个组件的位置可能是合适的 - 但即使这些情况是罕见的,也会导致您需要再次检查你的标准。

      4、抽象化

      基本元素与特定上下文是分离的,并能形成核心框架。

      我原先把这个原则称为“框架化”,因为除了创建你现在正在开发的一个特定项目之外,你还应该致力于创建一个超越原始上下文的设计系统。 这个原则是要确定贯穿在整个现有项目或未来项目中、需要使用的众多的通用要素。这个原则很宽泛,从页面排版和表单输入(form field inputs),直到各种导航设计。 这样思考:如果你的CSS将像Bootstrap或Foundation一样是一个开源的框架,你将如何区分这些设计元素? 你会如何对它们进行不同的设计? 即使你已经使用了Bootstrap,你的项目也可能包含一些Bootstrap不提供的基本元素,而这些元素也需要在项目的设计系统中是可用的。

      尽管我们的电子商务网站目前还没有这些设计元素,但是它们中的大部分对于使整个框架可用和抽象化,都是非常有帮助的。

      这里的关键是,用更通用的术语来考虑每个元素,而不是在项目的特定环境中。当你看一个特定元素时,把它分解成几个部分,然后给每个部分整体样式,不管你现在使用的具体实践如何,这个元素都会应当都会有这些样式。最常见的元素是排版(标题样式,行高,尺寸和字体),表单元素和按钮。但其他元素也应该“框架化”,如插图编号标签,或任何可能为我们的“每日优惠”设计的特殊价格格式,而且在其他地方也是有用的。

      在检查你项目的抽象性时,请问:

      •如果我知道在另一个需求不同的环境中要复用它,我将如何构建这个元素?

      •如何将其分解,以使它成在整个应用程序中有价值?

      考虑用更常规的方式来实现每个元素,这是思考的关键。这些部件应该被存储为完全独立的部分和类,或者更好的是作为独立的LESS或者Sass文件来存储,这些文件可以和最终的CSS一起被编辑。

      这个原则在Web组件或模块化的应用程序架构(module app architecture)中会更容易,因为这些小部件可能已经以这种方式分离了。但是,对于我们的思维的启示来说,它非常有益。我们应该始终将我们的工作从它自身的语境中抽象出来,以确保我们正在创造一些灵活的东西。

      5、模块化

      通用元素在逻辑上可被分解成可复用的组件。

      与“抽象”原则类似,使我们的设计模块化是建立一个易于使用和维护的具体设计系统的重要组成部分。两者之间有一条细线,但区分原则上的差异很重要。细微差别在于,总体基本要素需要从语境中抽象出来,而个别项目的背景也需要可被重复使用,并保持独立的风格。模块对于我们的应用程序来说可能是独一无二的,而不是我们在整个框架中需要的东西——但是它们仍然应该是可复用的,这样我们每次使用这个模块时都不需要重复代码。

      例如,如果您正在为一个日常交易登录页面实现之前例子中的产品卡片列表,与其使用类似daily-deal-product的class名——特意让HTML和CSS适用于这个页面;倒不如创建一个更一般的包含所有抽象类的名为“product-cards”的classs,而且这个类名还可以在交易页面之外重复使用。这可能会导致您的组件在三个独立的位置获取统一样式。

      基本CSS:这是底层框架,包括排版,槽宽,颜色和更多的默认值。

      •CSS组件:这些是设计的抽象部分,它们是构成总体设计的模块,但可以在任何语境下使用。

      •父组件:这些是“daily-deal”页面的组件(以及所有子组件),其中包含自定义或特定于此页面的样式。 对于很多人来说,这将是一个真正的JavaScript Web组件,但它可能只是一个父模板,其中包含呈现整个设计所必要的HTML。

      使你的实践“模块化”的结果应该是,让结果应该看起来像这样的——其中每个组件可能有一些间距或位置的样式,但大多数CSS是从框架继承的。

      当然,你可能觉得这个太过了,所以你必须做出判断。 但是大部分情况下,您创建的所有内容都应尽可能能重复使用,避免过度繁琐地进行长期维护。

      6、可配置

      通过可选参数来对基本元素进行自定义是可行的。

       构建设计系统的一部分是,要充分考虑项目现在或将来可能需要的选项。 只按照规定实现设计是不够的。 我们还必须考虑,通过不同的配置,哪些部分可能是可选、开启或关闭的。

      例如,我们设计中的标记“旗帜”只有三种颜色的变化,全部指向左侧。 我们将创建一个默认类,并添加额外的类名作为可选参数,而不是创建三个单独的类。 除此之外,我认为有人可能会过来,并希望将标记指向右侧以适用于不同的情况。 实际上,使用我们默认的品牌颜色来设计这些标注也是有用的,尽管设计并没有特别要求。 我们会专门编写CSS来解决这个问题,包括向左和向右的选项。

            我们的默认标记实际上使用默认的品牌颜色,而此处的标记具有特殊的以适用于此登录页的样式。 我们还会创建一些备选项,如不同颜色的,或指向右侧的。

      当你在思考特定的设计元素时,请考虑一些可能有价值的选项。 理解这一点的一个重要部分是,批判性地思考,这个元素是否可能在其他语境中被复用:

      •通过使用外部变量,哪些部件可以是可配置、可选和可用的?

      •元素的颜色或位置式可变的,这样做是否有价值?

      •提供小,中,大不同尺寸,这样是否真的有用?

      使用诸如BEM,OOCSS或SMACSS等方法组织您的CSS并建立命名规范,可以帮助您做出这些决定。解决这些问题,是构建可配置的设计系统的重要组成部分。

      7、可扩展

      该代码很容易扩展,并为未来的优化预留空间。 

      与“可配置”原则本质相同,我这个原则同样也须考虑未来的变化。 虽然建立可选参数是有用的,但我们不可能预料到我们项目未来需要的一切。 因此,重要的是要考虑我们写的代码将如何影响未来的变化,并有意识地组织它,这样才更容易去强化代码。

      要构建可扩展的CSS,通常需要我使用更高级的LESS和Sass特性来编写“mixin”和函数。 因为除了颜色外,我们所有的标记(注:下页中的旗帜图标)都是相同的,所以我们可以创建一个单独的LESS mixin,他可以为每个旗帜标记生成CSS,而不需要为每个变体重复代码。 该代码旨在便于扩展,并且很容易在一个地方进行更新。

      @angle: 170;

      .callout {

        &.qty-left {

          .callout-generator(@color-deals, @color-white, @angle);

        }

        &.qty-sold {

          .callout-generator(@color-white, @color-deals, @angle, 2px solid @color-deals);

        }

        &.qty-out {

          .callout-generator(@color-grey, darken(@color-grey, 10%), @angle);

        }

      }

      为了让旗帜标记可扩展,我们将创建一个LESS mixin,为了使标注可扩展,我们将创建一个名为.callout-generator的LESS mixin,它接受背景颜色、文本颜色、点和边框的角度等值。

       这样做生成的可扩展的CSS能够生成任意数量的新标注

      .review-flag {

          .callout-generator(@color-brand, @color-white, 75);

      }

      未来,当一个新的需求需要类似的设计样式时,产生一个新的样式将是容易的。

      要创建可扩展的设计系统,要学会预测项目中常见的变化,并运用这种理解来确保您编写的代码已经准备好适应这些变化。 常见的解决方案包括使用变量和mixin,以及在数组中存储值并循环遍历它们(looping through)。 问你自己:

      •这些元素的哪些部分可能会改变?

      •你讲如何编写代码,以便将来能更改适应这些变化?

      8、文档化

      所有元素都被有备注以便供他人使用和扩展。

       记录设计被低估,通常是项目中第一个被削减的角落。但是,创建工作记录不仅仅是帮助下一个人弄清楚你的意图——这实际上是让所有的利益相关者加入整个设计系统的好方法,这样你就不会每次都要重新发明车轮。您的文档应该作为团队中每个人的参考资料,从开发人员到管理人员。

      记录工作的最好方法是创建一个直接从代码中的注释生成的实时样式指南。我们使用一种称为“样式指南驱动的CSS开发文档 ”的方法。但是,即使你的项目不能有一个现场的风格指南,手动创建一个HTML或甚至打印格式的PDF也是好的。要记住的原则是我们所做的一切都必须记录下来。

      记录你的设计系统,并编写说明,以助其他人了解设计是如何实现的,以及他们自己需要做什么来重新创建设计。这些信息可能包括一个元素背后的具体设计思考、代码示例或动态元素的实例演示。

      •我怎样告诉别人如何使用我的代码?

      •如果我在给团队新成员作培训,我该怎么解释,以确保他们知道如何使用它?

      我该为每个插件展示怎样的变体,以演示它所有的使用方法?

       一个风格指南是伟大的,但直接从CSS生成的现场风格指南是意义非凡的。

      9、准确的

      最终输出能恰当地实现预期设计。

       最后,我们不能忘记,我们所创造的产品,必须与其最初的设计概念所要表达的内容是一致的。如果一个设计系统在视觉上就不符合预期,那么没有人会欣赏它。必须强调的是,设计结果只可能是设计的合适表达,并不是像素级的完美。我不喜欢“像素完美”这个词,因为它暗示最终效果必须和原型一样,精准到每个像素——这是故意忽略所有的约束条件和贬低标准化(在此请忽略每个浏览器在渲染CSS上的差异)。复杂的准确性是这样一个事实,即响应是的应用程序的静态设计很少考虑到每种可能的设备大小。这里的重点是,我们需要一定程度的灵活性。

      你必须决定,您的项目需要多少种适当的表示形式,但要确保符合您所共人员的期望。在我们的项目中,我将检查那些与客户在“像素级完美”上存在的主要偏差,以确保我们能达成共识。 “设计展示了一个带有边框的默认蓝色按钮样式,但是我们的标准按钮颜色略有不同,并且没有边框,所以我们选择了后者。”在这里,设置期望值是最重要的一步。

      用真实的数据和标准化的CSS生产,最终的实现效果看起来与最初原型略有不同。 此外,在实施过程中,一些要需求发生了变化。 然而,结果是准确的。

      小结:一种思维体系

      这九个原则的目标是为在HTML和CSS中实现设计提供一个指南。这不是一套规则或规范,它更多的是你工作中的一种思考方式,这样你就可以不断优化,以期达到优秀设计和优秀代码之间的最佳平衡。在应用这些原则时给自己一定的灵活性是很重要的。可能每一次你都无法使每个原则达到完美。他们是理想。总是有其他的干扰、原则和优先事项,使我们无法将工作做到最好。尽管如此,这些原则应该是永远追求的目标,我们需要不断地检查自己,并且在将设计从绘图板转移到最终的将被用户使用的媒介上时,积极地追求这些目标。我希望它们会帮助你创造更好的产品,并建立可持续多年的设计系统。

      原文地址:

      《The Nine Principles Of Design Implementation》

      Tom Greever 于2017年8月14发表于《Smashing magazine》(一个知名的“用户体验+前端设计”分享网站)

      在翻译过程中,为了解各种前端概念(当然,只是皮毛),自己也找了一些浅显易懂的文章:

      《BEM —— 源自Yandex的CSS 命名方法论》

      《瞎扯扯OOCSS,ACSS,BEM,SMACSS》

      《为什么要使用Sass》

      《浅谈sass与less区别优缺点》

    • 最后编辑于
      ©著作权归作者所有,转载或内容合作请联系作者
      • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
        沈念sama阅读 212,029评论 6 492
      • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
        沈念sama阅读 90,395评论 3 385
      • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
        开封第一讲书人阅读 157,570评论 0 348
      • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
        开封第一讲书人阅读 56,535评论 1 284
      • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
        茶点故事阅读 65,650评论 6 386
      • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
        开封第一讲书人阅读 49,850评论 1 290
      • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
        沈念sama阅读 39,006评论 3 408
      • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
        开封第一讲书人阅读 37,747评论 0 268
      • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
        沈念sama阅读 44,207评论 1 303
      • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
        茶点故事阅读 36,536评论 2 327
      • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
        茶点故事阅读 38,683评论 1 341
      • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
        沈念sama阅读 34,342评论 4 330
      • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
        茶点故事阅读 39,964评论 3 315
      • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
        开封第一讲书人阅读 30,772评论 0 21
      • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
        开封第一讲书人阅读 32,004评论 1 266
      • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
        沈念sama阅读 46,401评论 2 360
      • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
        茶点故事阅读 43,566评论 2 349

      推荐阅读更多精彩内容