<p style="box-sizing: border-box; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap; margin-top: 0px !important;"><strong style="box-sizing: border-box;">1、CSS 字体</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">CSS字体属性定义字体,加粗,大小,文字样式。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">serif和sans-serif字体之间的区别</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在计算机屏幕上,sans-serif字体被认为是比serif字体容易阅读</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">2、CSS字型</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在CSS中,有两种类型的字体系列名称:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">通用字体系列 - 拥有相似外观的字体系统组合(如 “Serif” 或 “Monospace”)</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">特定字体系列 - 一个特定的字体系列(如 “Times” 或 “Courier”)</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">3、字体系列</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">font-family 属性设置文本的字体系列。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">font-family 属性应该设置几个字体名称作为一种”后备”机制,如果浏览器不支持第一种字体,他将尝试下一种字体。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">注意: 如果字体系列的名称超过一个字,它必须用引号,如Font Family:”宋体”。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">多个字体系列是用一个逗号分隔指明:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">p{ font-family:"Times New Roman", Times, serif; }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">对于较常用的字体组合,看看我们的 Web安全字体组合。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">4、字体样式</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">主要是用于指定斜体文字的字体样式属性。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">这个属性有三个值:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">正常 - 正常显示文本</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">斜体 - 以斜体字显示的文字</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">倾斜的文字 - 文字向一边倾斜(和斜体非常类似,但不太支持)</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">p.normal { font-style:normal; } p.italic { font-style:italic; } p.oblique { font-style:oblique; }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">5、字体大小</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">font-size 属性设置文本的大小。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">能否管理文字的大小,在网页设计中是非常重要的。但是,你不能通过调整字体大小使段落看上去像标题,或者使标题看上去像段落。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">请务必使用正确的HTML标签,就<code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);"><h1> - <h6></code>表示标题和<code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);"><p></code>表示段落:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">字体大小的值可以是绝对或相对的大小。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">6、绝对大小</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">设置一个指定大小的文本</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">不允许用户在所有浏览器中改变文本大小</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">确定了输出的物理尺寸时绝对大小很有用</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">7、相对大小</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">相对于周围的元素来设置大小</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">允许用户在浏览器中改变文字大小</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">如果你不指定一个字体的大小,默认大小和普通文本段落一样,是16像素(16px=1em)。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">8、设置字体大小像素</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">设置文字的大小与像素,让您完全控制文字大小:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">h1 { font-size:40px; } h2 { font-size:30px; } p { font-size:14px; }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">上面的例子可以在 Internet Explorer 9, Firefox, Chrome, Opera, 和 Safari 中通过缩放浏览器调整文本大小。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">虽然可以通过浏览器的缩放工具调整文本大小,但是,这种调整是整个页面,而不仅仅是文本</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">9、用em来设置字体大小</strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">为了避免Internet Explorer 中无法调整文本的问题,许多开发者使用 em 单位代替像素。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">em的尺寸单位由W3C建议。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">1em和当前字体大小相等。在浏览器中默认的文字大小是16px。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">因此,1em的默认大小是16px。可以通过下面这个公式将像素转换为em:px/16=em</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">h1 { font-size:2.5em; } /* 40px/16=2.5em */ h2 { font-size:1.875em; } /* 30px/16=1.875em */ p { font-size:0.875em; } /* 14px/16=0.875em */</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在上面的例子,em的文字大小是与前面的例子中像素一样。不过,如果使用 em 单位,则可以在所有浏览器中调整文本大小。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">不幸的是,仍然是IE浏览器的问题。调整文本的大小时,会比正常的尺寸更大或更小。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">使用百分比和EM组合</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在所有浏览器的解决方案中,设置 <body>元素的默认字体大小的是百分比:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap; margin-bottom: 0px !important;">body { font-size:100%; } h1 { font-size:2.5em; } h2 { font-size:1.875em; } p { font-size:0.875em; }</pre><p><br/></p>
文章列表
<p><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">1. 文本颜色</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">color</code>属性用于设置文本的颜色。颜色由以下值指定:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>十六进制值 - 如: #FF0000</p></li><li><p>一个RGB值 - 如: RGB(255,0,0)</p></li><li><p>颜色的名称 - 如: red</p></li></ul><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">一般页面的默认文本颜色是在 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">body</code> 选择器中定义的,也可以针对指定元素设置具体的文本颜色,实例如下:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body { color:red; } h1 { color:#00ff00; } h2 { color:rgb(255,0,0); }</pre><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">2. 文本的对齐方式</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">text-align</code>属性是用来设置文本的水平对齐方式,可以设置文本左对齐、右对齐、居中对齐和两端对齐。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">h1 {text-align:center;}<br/>p {text-align:right;}<br/>p {text-align:justify;}<br/>div {text-align: justify;}</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">3. 文本装饰</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">text-decoration</code> 属性用来设置或删除文本的装饰,规定添加到文本的修饰,下划线、上划线、删除线等。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:<br/>a {text-decoration:none;}<br/>h1 {text-decoration:overline;}<br/>h2 {text-decoration:line-through;}<br/>h3 {text-decoration:underline;}</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">4. 文本转换</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">text-transform</code>属性是用来指定在一个文本中的大写和小写字母,可用于所有字句变成大写或小写字母,或每个单词的首字母大写等。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">实例:<br/>p.uppercase {text-transform:uppercase;}<br/>p.lowercase {text-transform:lowercase;}<br/>p.capitalize {text-transform:capitalize;}</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">5. 文本缩进</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">text-indent</code>属性用于规定文本块中首行文本的缩进,语法为text-indent : length | % 。该属性允许使用负值;如果使用负值,那么首行会被缩进到左边。</p><p style="box-sizing: border-box; margin-top: 0px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap; margin-bottom: 0px !important;">实例:<br/>p {text-indent:50px;}</p><p><br/></p>
<p><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;"><strong>1、CSS 背景</strong></span></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">CSS 背景属性用于定义HTML元素的背景。<br/>CSS 属性定义背景效果:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">background-color background-image background-repeat background-attachment background-position</pre><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><span style="font-size: 14px; font-family: 微软雅黑, "Microsoft YaHei";"><strong>2. 背景颜色</strong></span></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">background-color 属性定义了元素的背景颜色。<br/>页面的背景颜色使用在body的选择器中:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body { background-color:#b0c4de; }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">CSS中,颜色值通常以以下方式定义:<br/>十六进制 - 如:"#ff0000"<br/>RGB - 如:"rgb(255,0,0)"<br/>颜色名称 - 如:"red"<br/>以下实例中, h1, p, 和 div 元素拥有不同的背景颜色:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">h1 { background-color:#6495ed; } p { background-color:#e0ffff; } div { background-color:#b0c4de; }</pre><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">3. 背景图像</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">background-image 属性描述了元素的背景图像。<br/>默认情况下,背景图像进行平铺重复显示,以覆盖整个元素实体。<br/>页面背景图片设置实例:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body { background-image:url('paper.gif'); }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">下面是一个例子是一个糟糕的文字和背景图像组合。文本可读性差:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body { background-image:url('bgdesert.jpg'); }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">背景图像 - 水平或垂直平铺<br/>默认情况下 background-image 属性会在页面的水平或者垂直方向平铺。<br/>一些图像如果在水平方向与垂直方向平铺,这样看起来很不协调,如下所示:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body{ background-image:url('gradient2.png'); }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">如果图像只在水平方向平铺 (repeat-x), 页面背景会更好些:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body{ background-image:url('gradient2.png'); background-repeat:repeat-x; }</pre><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">4.背景图像 - 设置定位与不平铺</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">让背景图像不影响文本的排版<br/>如果你不想让图像平铺,你可以使用 background-repeat 属性:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body{ background-image:url('img_tree.png'); background-repeat:no-repeat; }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">以上实例中,背景图像与文本显示在同一个位置,为了让页面排版更加合理,不影响文本的阅读,我们可以改变图像的位置。<br/>可以利用 background-position 属性改变图像在背景中的位置:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body{ background-image:url('img_tree.png'); background-repeat:no-repeat; background-position:right top; }</pre><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">5. 背景 - 简写属性</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在以上实例中我们可以看到页面的背景颜色通过了很多的属性来控制。<br/>为了简化这些属性的代码,我们可以将这些属性合并在同一个属性中。<br/>背景颜色的简写属性为 “background”:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p>实例</p></li></ul><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">body { background:#ffffff url('img_tree.png') no-repeat right top; }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">当使用简写属性时,属性值的顺序为:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">background-color background-image background-repeat background-attachment background-position</pre><p style="box-sizing: border-box; margin-top: 0px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap; margin-bottom: 0px !important;">以上属性无需全部使用,你可以按照页面的实际需要使用。</p>
<blockquote style="box-sizing: border-box; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; border-left: 4px solid rgb(238, 238, 238); font-size: 14px; padding: 0px 15px 0px 20px; color: rgb(102, 102, 102); font-style: italic; font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap; margin-top: 0px !important;"><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;">Cookie 是一个请求首部,其中含有先前由服务器通过 Set-Cookie 首部投放并存储到客户端的 HTTP cookies。</p></blockquote><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">cookie 可以作为单独知识了解,这里其实介绍的是 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">document.cookie</code> 。</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">1. document.cookie</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">通过 document.cookie 可以获取与设置 cookie 。</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">2. 获取 cookie</span></strong></p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">document.cookie;</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">通过 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">document.cookie</code> 获取到的 cookie 由 cookie 的名称和值组成,由等号<code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">=</code>分隔,并且可以有多条,每条 cookie 之间用分号 ‘;’ 分隔。</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">3. 设置cookie</span></strong></p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">var cookie = 'cookie名称=cookie值'; document.cookie = cookie;</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">设置 cookie 采用<code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">键值对</code>的形式。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">对应的就是 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">cookie的名称</code> 和 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">cookie值</code> 。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><strong style="box-sizing: border-box;">每次只能设置一条 cookie</strong> ,但可以同时设置这条 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">cookie的属性</code> 。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">如果需要设置多条 cookie ,则再次给 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">document.cookie</code> 赋一个新值即可,但如果是相同名称的 cookie ,值就会被覆盖。</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">4. 设置 cookie 属性</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">设置 cookie 的同时可以设置这条 cookie 的属性。</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">document.cookie = '名称=值; 属性1=属性值1; 属性2=属性值2';</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">看起来是可以设置多条 cookie 一样,其实只有第一对值才是 cookie 的值,后面跟的都是这条 cookie 的属性。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">可以跟随的属性有:</p><ul style="box-sizing: border-box; margin-bottom: 16px; padding: 0px 0px 0px 2em; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;" class=" list-paddingleft-2"><li><p><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">path</code> cookie 生效的路径</p></li><li><p><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">domain</code> cookie 生效的域名</p></li><li><p><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">max-age</code> 过期时间,单位是秒</p></li><li><p><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">expires</code> 过期时间,为一个 UTC 时间</p></li><li><p><code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">secure</code> 是否只能通过 https 来传递这条 cookie</p></li></ul><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">这些属性具体作用可以参考 cookie 相关的内容。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">设置完属性可以通过开发者工具查看。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在开发者工具的 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">Application</code> 面板,<code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">cookie</code> 分类下,每一条 cookie 都可以看到对应的属性。</p><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei"; font-size: 14px;">5. 注意点:</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">由于设置 cookie 是具有一定格式的,所以不能有字符来干扰这个格式。</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">var cookie = 'code=var a = 1; var b = 2;'; document.cookie = cookie;</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">这种情况下,cookie 就不符合预期了,被切断。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">cookie 中不应该含有空格、分号、逗号这些符号。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">借助 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">encodeURIComponent</code> 方法,对 cookie 的值进行编码就可以避免这类问题。</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">var cookie = 'code=' + encodeURIComponent('var a = 1; var b = 2;'); document.cookie = cookie;</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">后续需要使用到这一条 cookie 的地方,再做一次解码操作即可。</p><blockquote style="box-sizing: border-box; margin: 0px 0px 16px; border-left: 4px solid rgb(238, 238, 238); font-size: 14px; padding: 0px 15px 0px 20px; color: rgb(102, 102, 102); font-style: italic; font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;"><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;">注意:对字符串编码还可以使用 escape 方法,但已经从标准中移除,目前浏览器虽然还支持这个方法,但无法保证永远会保留这个方法,最好避免使用 escape 方法。</p></blockquote><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a><strong><span style="font-family: 微软雅黑, "Microsoft YaHei";">6. 总结:</span></strong></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">随着前端存储方案的增加,前端程序员访问 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">document.cookie</code> 相对曾经减少了很多。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">给 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">document.cookie</code> 赋值可以增加一条 cookie,同时通过 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">;</code> 相隔,来设置这条 cookie 的属性。</p><p style="box-sizing: border-box; margin-top: 0px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap; margin-bottom: 0px !important;">当设置的 cookie 带有特殊字符的时候,如 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">;</code> 或者 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">=</code>,应采用 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">encodeURIComponent</code> 对内容编码,建议所有的 cookie 都进行编码。</p><p><br/></p>
<blockquote style="box-sizing: border-box; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; border-left: 4px solid rgb(238, 238, 238); font-size: 14px; padding: 0px 15px 0px 20px; color: rgb(102, 102, 102); font-style: italic; font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap; margin-top: 0px !important;"><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;">with 语句就可以扩展一个语句的作用域链。——MDN</p></blockquote><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">with 可以指定代码块的作用域,特别是在访问对象成员时,它使得代码非常简洁。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">1、基本语法</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">with (表达式) { 代码块;}</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">表达式通常会直接给定一个对象。</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">var person = { name: '小明', age: 666, major: 'english',}; with (person) { console.log(name); // 输出:"小明" console.log(age); // 输出:666 console.log(major); // 输出:"english" }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">可以看到,with 代码块内输出的变量,实际上是 <code style="box-sizing: border-box; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; color: rgb(232, 62, 140); overflow-wrap: break-word; padding: 3px; margin: 0px 4px 0px 5px; background: rgb(246, 246, 246); border-radius: 3px; border: 1px solid rgb(238, 238, 238);">person</code> 对象的属性。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">在 with 语句中,访问变量会先去看这个变量是不是在给定的对象中作为属性存在,如果存在,则取对象中属性的值,否则继续往上层找。<span style="font-family: 微软雅黑, "Microsoft YaHei"; letter-spacing: 0.5px;">不</span><span style="font-family: 微软雅黑, "Microsoft YaHei"; letter-spacing: 0.5px;">推荐使用 w</span><span style="font-family: 微软雅黑, "Microsoft YaHei"; letter-spacing: 0.5px;">ith</span></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">尽管 with 很方便,但 with 会造成诸多的问题。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">2.1 造成语义不明</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">先看这段代码:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">function fn(block, height) { with (block) { console.log(height); }}</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">这样的代码,有点让阅读代码的人难以理解具体含义。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">阅读代码的时候,无法确定 height 要取 block 下的属性,还是要取形参 height。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">2.2 造成污染</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">function fn(obj) { with (obj) { b = 1; } }</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">这个场景其实和上面的类似,假如 obj 中没有属性 b ,则会造成上层作用域的污染。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;"><img src="https://www.maxiaoke.com/uploads/images/20230214/2679de3a45c62b24b6717e623e4e3a54.jpeg" alt=""/></p><hr/><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">事实上很少有前端开发者会使用 with,在很长篇幅的代码中,with 会让代码逻辑变得不清晰,需要反复确认作用域。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">尽可能的避免使用 with ,使用短变量名和合理的空行来使代码变得整洁易懂。</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 11.9px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">var family = [{ seniority: '子', name: '小明', detail: { birth: '1192/01/22', sex: 'man', hand: 8, leg: 44, deposit: 9999 }, }]; // 不好的表述形式 family[0].detail.birth = '1122/22/11'; family[0].detail.sex = '?'; var deposit = family[0].detail.family[0].detail; // 取出要操作的数据并控制空行 var detail = family[0].detail; detail.birth = '2312/22/33'; detail.sex = '未知性别'; var deposit = detail.deposit;</pre><p><a class="reference-link" style="box-sizing: border-box; color: rgb(51, 202, 187); background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial; transition: all 0.3s linear 0s; outline: none !important;"></a>总结:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">with 的使用需要谨慎,尽量在可控范围内使用。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(51, 51, 51); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; font-size: 14px; text-wrap: wrap;">使用 with 常见的遇到问题的情况,都是恰巧污染了上层作用域,又恰巧污染的是同名的变量,这也产生的 bug 定位也相对困难。</p><blockquote style="box-sizing: border-box; margin-top: 0px; margin-right: 0px; margin-left: 0px; border-left: 4px solid rgb(238, 238, 238); font-size: 14px; padding: 0px 15px 0px 20px; color: rgb(102, 102, 102); font-style: italic; font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap; margin-bottom: 0px !important;"><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 0px;">前端框架 Vue 将 template 转化成 render 函数的时候就用到了 with。</p></blockquote><p><br/></p>
<p><strong><span style="text-wrap: nowrap;">break 与 continue 用来控制循环流程。</span></strong></p><p><strong><span style="text-wrap: nowrap;">1、break</span></strong></p><p><span style="text-wrap: nowrap;">break 用来中断循环,在 for 循环和 while 循环中都适用。</span><br/></p><p><span style="text-wrap: nowrap;">如:从列表中寻找 id 为 n 的项(每一项的 id 是唯一的)</span><span style="text-wrap: nowrap;"> </span></p><pre class="brush:js;toolbar:false">var list = [{ id: 1 }, { id: 4 }, { id: 9 }, { id: 2 }]; var n = 9; var i = 0, len = list.length; for (; i < len; i++) { console.log(i); if (list[i].id === n) { console.log(list[i]); break; } }</pre><p><span style="text-wrap: nowrap;">其实即便没有 break,上面的语句也可以正常执行,因为 id 是唯一的,即便将整个数组遍历完,也只有一个目标项。</span></p><p><span style="text-wrap: nowrap;">但是如果整个列表有'上万'条数据,除了获取 id ,还有一些消耗性能的操作,那 break 就变得很关键。 </span></p><p><span style="text-wrap: nowrap;">假如最好的情况,寻找的项就在第一项,这时候碰到 break ,剩下无用的寻找操作就都不会执行了,也没有必要执行。</span></p><p><span style="text-wrap: nowrap;">将 break 应用在 while 中也是同理,满足某些条件的时候用来中断 while 循环。</span><br/></p><p><span style="text-wrap: nowrap;">如:游戏中的怪物产生了 4 次连击,伤害由四个随机 100 至 2000 的值累加构成,假如在累加的伤害过程中值达到 5000,则直接取当前累加结果作为最终伤害。</span></p><pre class="brush:js;toolbar:false">var total = 0; // 累积伤害 var time = 1; // 累加次数 while (time <= 4) { var one = Math.floor(Math.random() * 2001 + 100); console.log(one); total += one; if (total > 5000) { break; } time++; }</pre><p><span style="text-wrap: nowrap;">通过 break,可以很容易的达到这个需求。</span></p><p><span style="text-wrap: nowrap;">当然不使用 break 也是可以的,可以在达到条件后,将 `time` 变量累加到一个循环条件不成立的情况,也会跳出循环,但是建议使用 break ,否则可能还要去控制 break 之后的逻辑,因为</span></p><p><span style="text-wrap: nowrap;">break 之后不一定就是循环结束了,也许还有其他操作。</span></p><p><strong><span style="text-wrap: nowrap;">2、continue</span></strong><br/></p><p><span style="text-wrap: nowrap;">当循环中碰到 continue ,则会跳过这次循环,进入下一次循环。</span></p><p><span style="text-wrap: nowrap;">如:输出 0 至 100 之间的奇数</span><span style="text-wrap: nowrap;"> </span></p><pre class="brush:js;toolbar:false">var i; for (i = 0; i <= 100; i++) { if (i % 2 === 0) { continue; } console.log(i); }</pre><p><span style="text-wrap: nowrap;">当碰到偶数的时候,则跳过这次循环,反之则为奇数的情况,会输出值。</span></p><p><span style="text-wrap: nowrap;">这个例子比较简单,当一个逻辑复杂的循环体出现的时候,continue 可以让代码块变得稍微简洁。</span></p><p><span style="text-wrap: nowrap;">如:对用户列表进行批量操作,只操作 id (id 一定是数字) 末尾为 1 的用户。</span><span style="text-wrap: nowrap;"> </span></p><pre class="brush:js;toolbar:false">// 这是一份伪代码 var users = [ ... 很多用户 ]; var i, len; for (i = 0, len = users.length; i < len; i++) { var user = users[i]; if (user.id % 10 === 1) { // 取到末尾 continue; } if (user.edition) { // 如果用户的版本不是免费的 0是免费 其他则是收费 // 做一些操作 } if (user.money) { // 如果用户有余额 // 做一些操作 } // ... }</pre><p><span style="text-wrap: nowrap;">像这样,通过 continue 就可以让流程更清晰。</span></p><p><span style="text-wrap: nowrap;">在 while 中的应用是一样的,continue 也可以在 while 中跳过当前循环。</span></p><p><span style="text-wrap: nowrap;">使用 while 输出 0 至 100 的奇数:</span></p><pre class="brush:js;toolbar:false">var num = -1; while (num < 100) { num++; if (num % 2 === 0) { continue; } console.log(num); }</pre><p><span style="text-wrap: nowrap;">整个流程与 for 循环非常相似。</span></p><p><span style="text-wrap: nowrap;">许多代码规范不提倡使用 continue ,因为开发者水平的参差不齐,常有开发者在使用 continue 的时候,让整体逻辑产生了跳跃性,这不利于未来的代码维护者来对代码做阅读理解。</span></p><p><strong><span style="text-wrap: nowrap;">3、总结:</span></strong></p><p><span style="text-wrap: nowrap;">break 和 continue 适用于 for 循环和 while 循环。</span></p><p><span style="text-wrap: nowrap;">continue 的使用没有 break 频繁,使用 continue 的时候需要注意,尽量不要使程序跳跃幅度过大,不利于后期维护。</span></p><p><span style="text-wrap: nowrap;">所有需要使用 continue 的地方,都可以不使用 continue 实现。</span></p><p><span style="text-wrap: nowrap;">switch 语句中也可以使用 break 来结束 switch 语句的执行。</span></p>
<p><span style="text-wrap: nowrap;">Vue中组件间通信的方法:provide / inject 和 dispatch / broadcast。它们有各自的使用场景和局限,比如前者多用于子组件获取父组件的状态,后者常用于父子组件间通过自定义事件通信。</span><br/></p><p><span style="text-wrap: nowrap;">本文将介绍第 3 种组件通信方法,也就是 findComponents 系列方法,它并非 Vue.js 内置,而是需要自行实现,以工具函数的形式来使用,它是一系列的函数,可以说是组件通信的终极方案。</span></p><p><span style="text-wrap: nowrap;">findComponents 系列方法最终都是返回组件的实例,进而可以读取或调用该组件的数据和方法。</span></p><p><span style="text-wrap: nowrap;">它适用于以下场景:</span></p><p><span style="text-wrap: nowrap;">* 由一个组件,向上找到最近的指定组件;</span></p><p><span style="text-wrap: nowrap;">* 由一个组件,向上找到所有的指定组件;</span></p><p><span style="text-wrap: nowrap;">* 由一个组件,向下找到最近的指定组件;</span></p><p><span style="text-wrap: nowrap;">* 由一个组件,向下找到所有指定的组件;</span></p><p><span style="text-wrap: nowrap;">* 由一个组件,找到指定组件的兄弟组件。</span></p><p><span style="text-wrap: nowrap;">5 个不同的场景,对应 5 个不同的函数,实现原理也大同小异。</span></p><p><strong><span style="text-wrap: nowrap;">实现</span></strong></p><p><span style="text-wrap: nowrap;">5 个函数的原理,都是通过递归、遍历,找到指定组件的 `name` 选项匹配的组件实例并返回。</span><span style="text-wrap: nowrap;">在目录 `src` 下新建文件夹 `utils` 用来放置工具函数,并新建文件 `assist.js`,本文所有函数都在这个文件里完成,每个函数都通过 `export` 对外提供(如果你不了解 export,请查看扩展阅读)</span></p><p><span style="text-wrap: nowrap;">向上找到最近的指定组件——findComponentUpward</span><br/></p><p><span style="text-wrap: nowrap;">先看代码:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// assist.js // 由一个组件,向上找到最近的指定组件 function findComponentUpward (context, componentName) { let parent = context.$parent; let name = parent.$options.name; while (parent && (!name || [componentName].indexOf(name) < 0)) { parent = parent.$parent; if (parent) name = parent.$options.name; } return parent; } export { findComponentUpward };</pre><p><span style="text-wrap: nowrap;">findComponentUpward 接收两个参数,第一个是当前上下文,比如你要基于哪个组件来向上寻找,一般都是基于当前的组件,也就是传入 `this`;第二个参数是要找的组件的 `name` 。</span></p><p><span style="text-wrap: nowrap;">findComponentUpward 方法会在 while 语句里不断向上覆盖当前的 `parent` 对象,通过判断组件(即 parent)的 name 与传入的 componentName 是否一致,直到直到最近的一个组件为</span><br/></p><p><span style="text-wrap: nowrap;">止。</span></p><p><span style="text-wrap: nowrap;">与 dispatch 不同的是,findComponentUpward 是直接拿到组件的实例,而非通过事件通知组件。比如下面的示例,有组件 A 和组件 B,A 是 B 的父组件,在 B 中获取和调用 A 中的数据和</span><br/></p><p><span style="text-wrap: nowrap;">方法:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- component-a.vue --> <template> <div> 组件 A <component-b></component-b> </div> </template> <script> import componentB from './component-b.vue'; export default { name: 'componentA', components: { componentB }, data () { return { name: 'Aresn' } }, methods: { sayHello () { console.log('Hello, Vue.js'); } } } </script> <!-- component-b.vue --> <template> <div> 组件 B </div> </template> <script> import { findComponentUpward } from '../utils/assist.js'; export default { name: 'componentB', mounted () { const comA = findComponentUpward(this, 'componentA'); if (comA) { console.log(comA.name); // Aresn comA.sayHello(); // Hello, Vue.js } } } </script></pre><p><span style="text-wrap: nowrap;">使用起来很简单,只要在需要的地方调用 findComponentUpward 方法就行,第一个参数一般都是传入 this,即当前组件的上下文(实例)。</span></p><p><span style="text-wrap: nowrap;">上例的 comA,保险起见,加了一层 `if (comA)` 来判断是否找到了组件 A,如果没有指定的组件而调用的话,是会报错的。</span></p><p><span style="text-wrap: nowrap;">findComponentUpward 只会找到最近的一个组件实例,如果要找到全部符合要求的组件,就需要用到下面的这个方法。</span></p><p><span style="text-wrap: nowrap;"><strong>向上找到所有的指定组件——findComponentsUpward</strong></span></p><p><span style="text-wrap: nowrap;">代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// assist.js // 由一个组件,向上找到所有的指定组件 function findComponentsUpward (context, componentName) { let parents = []; const parent = context.$parent; if (parent) { if (parent.$options.name === componentName) parents.push(parent); return parents.concat(findComponentsUpward(parent, componentName)); } else { return []; } } export { findComponentsUpward };</pre><p><span style="text-wrap: nowrap;">与 findComponentUpward 不同的是,findComponentsUpward 返回的是一个数组,包含了所有找到的组件实例(注意函数名称中多了一个“s”)。</span></p><p><span style="text-wrap: nowrap;">findComponentsUpward 的使用场景较少,一般只用在递归组件里面(后面小节会介绍),因为这个函数是一直向上寻找父级(parent)的,只有递归组件的父级才是自身。事实上,iView </span></p><p><span style="text-wrap: nowrap;">在使用这个方法也都是用在递归组件的场景,比如菜单组件 Menu。由于递归组件在 Vue.js 组件里面并不常用,那自然 findComponentsUpward 也不常用了。</span></p><p><span style="text-wrap: nowrap;"><strong>向下找到最近的指定组件——findComponentDownward</strong></span></p><p><span style="text-wrap: nowrap;">代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// assist.js // 由一个组件,向下找到最近的指定组件 function findComponentDownward (context, componentName) { const childrens = context.$children; let children = null; if (childrens.length) { for (const child of childrens) { const name = child.$options.name; if (name === componentName) { children = child; break; } else { children = findComponentDownward(child, componentName); if (children) break; } } } return children; } export { findComponentDownward };</pre><p><span style="text-wrap: nowrap;">`context.$children` 得到的是当前组件的全部子组件,所以需要遍历一遍,找到有没有匹配到的组件 `name`,如果没找到,继续递归找每个 $children 的 $children,直到找到最近的一个为止。</span></p><p><span style="text-wrap: nowrap;">来看个示例,仍然是 A、B 两个组件,A 是 B 的父组件,在 A 中找到 B:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- component-b.vue --> <template> <div> 组件 B </div> </template> <script> export default { name: 'componentB', data () { return { name: 'Aresn' } }, methods: { sayHello () { console.log('Hello, Vue.js'); } } } </script> <!-- component-a.vue --> <template> <div> 组件 A <component-b></component-b> </div> </template> <script> import componentB from './component-b.vue'; import { findComponentDownward } from '../utils/assist.js'; export default { name: 'componentA', components: { componentB }, mounted () { const comB = findComponentDownward(this, 'componentB'); if (comB) { console.log(comB.name); // Aresn comB.sayHello(); // Hello, Vue.js } } } </script></pre><p><span style="text-wrap: nowrap;">示例中的 A 和 B 是父子关系,因此也可以直接用 `ref` 来访问,但如果不是父子关系,中间间隔多代,用它就很方便了。</span></p><p><strong><span style="text-wrap: nowrap;">向下找到所有指定的组件——findComponentsDownward</span></strong></p><p><span style="text-wrap: nowrap;">如果要向下找到所有的指定组件,要用到 findComponentsDownward 函数,代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// assist.js // 由一个组件,向下找到所有指定的组件 function findComponentsDownward (context, componentName) { return context.$children.reduce((components, child) => { if (child.$options.name === componentName) components.push(child); const foundChilds = findComponentsDownward(child, componentName); return components.concat(foundChilds); }, []); } export { findComponentsDownward };</pre><p><span style="text-wrap: nowrap;">这个函数实现的方式有很多,这里巧妙使用 `reduce` 做累加器,并用递归将找到的组件合并为一个数组并返回,代码量较少,但理解起来稍困难。</span></p><p><span style="text-wrap: nowrap;">用法与 findComponentDownward 大同小异,就不再写用例了。</span></p><p><strong><span style="text-wrap: nowrap;">找到指定组件的兄弟组件——findBrothersComponents</span></strong></p><p><span style="text-wrap: nowrap;">代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// assist.js // 由一个组件,找到指定组件的兄弟组件 function findBrothersComponents (context, componentName, exceptMe = true) { let res = context.$parent.$children.filter(item => { return item.$options.name === componentName; }); let index = res.findIndex(item => item._uid === context._uid); if (exceptMe) res.splice(index, 1); return res; } export { findBrothersComponents };</pre><p><span style="text-wrap: nowrap;">相比其它 4 个函数,findBrothersComponents 多了一个参数 `exceptMe`,是否把本身除外,默认是 true。寻找兄弟组件的方法,是先获取 `context.$parent.$children`,也就是父组件的全</span></p><p><span style="text-wrap: nowrap;">部子组件,这里面当前包含了本身,所有也会有第三个参数 exceptMe。Vue.js 在渲染组件时,都会给每个组件加一个内置的属性 `_uid`,这个 \_uid 是不会重复的,借此我们可以从一系列兄弟</span></p><p><span style="text-wrap: nowrap;">组件中把自己排除掉。</span></p><p><span style="text-wrap: nowrap;">举个例子,组件 A 是组件 B 的父级,在 B 中找到所有在 A 中的兄弟组件(也就是所有在 A 中的 B 组件):</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- component-a.vue --> <template> <div> 组件 A <component-b></component-b> </div> </template> <script> import componentB from './component-b.vue'; export default { name: 'componentA', components: { componentB } } </script> <!-- component-b.vue --> <template> <div> 组件 B </div> </template> <script> import { findBrothersComponents } from '../utils/assist.js'; export default { name: 'componentB', mounted () { const comsB = findBrothersComponents(this, 'componentB'); console.log(comsB); // ① [],空数组 } } </script></pre><p><span style="text-wrap: nowrap;">在 ① 的位置,打印出的内容为空数组,原因是当前 A 中只有一个 B,而 findBrothersComponents 的第三个参数默认是 true,也就是将自己除外。如果在 A 中再写一个 B:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- component-a.vue --> <template> <div> 组件 A <component-b></component-b> <component-b></component-b> </div> </template></pre><p><span style="text-wrap: nowrap;">这时就会打印出 `[VueComponent]`,有一个组件了,但要注意在控制台会打印两遍,因为在 A 中写了两个 B,而 `console.log` 是在 B 中定义的,所以两个都会执行到。如果你看懂了这里,</span></p><p><span style="text-wrap: nowrap;">那应该明白打印的两遍 `[VueComponent]`,分别是另一个 `<component-b>`(如果没有搞懂,要仔细琢磨琢磨哦)。</span></p><p><span style="text-wrap: nowrap;">如果将 B 中 findBrothersComponents 的第三个参数设置为 false:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// component-b.vue export default { name: 'componentB', mounted () { const comsB = findBrothersComponents(this, 'componentB', false); console.log(comsB); } }</pre><p><span style="text-wrap: nowrap;">此时就会打印出 `[VueComponent, VueComponent]`,也就是包含自身了。</span></p><p><span style="text-wrap: nowrap;">以上就是 5 个函数的详细介绍,get 到这 5 个,以后就再也不用担心组件通信了。</span></p><p><br/></p><p><strong><span style="text-wrap: nowrap;">扩展阅读</span></strong></p><p><span style="text-wrap: nowrap;">* [ES6 Module 的语法](http://es6.ruanyifeng.com/#docs/module)</span><br/></p>
<p><strong><span style="text-wrap: nowrap;">实战:具有数据校验功能的表单组件——Form</span></strong></p><p><span style="text-wrap: nowrap;">本文基于这组件间的通信方法,来实现一个具有数据校验功能的表单组件——Form。</span></p><p><strong><span style="text-wrap: nowrap;">Form 组件概览</span></strong></p><p><span style="text-wrap: nowrap;">表单类组件在项目中会大量使用,比如输入框(Input)、单选(Radio)、多选(Checkbox)、下拉选择器(Select)等。在使用表单类组件时,也会经常用到数据校验,如果每次都写校验程</span></p><p><span style="text-wrap: nowrap;">序来对每一个表单控件校验,会很低效,因此需要一个能够校验基础表单控件的组件,也就是本节要完成的 Form 组件。一般的组件库都提供了这个组件,比如 iView,它能够校验内置的 15 种</span></p><p><span style="text-wrap: nowrap;">控件,且支持校验自定义组件。</span></p><p><span style="text-wrap: nowrap;">Form 组件分为两个部分,一个是外层的 `Form` 表单域组件,一组表单控件只有一个 Form,而内部包含了多个 `FormItem` 组件,每一个表单控件都被一个 FormItem 包裹。基本的结构看起</span></p><p><span style="text-wrap: nowrap;">来像:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><i-form> <i-form-item> <i-input v-model="form.name"></i-input> </i-form-item> <i-form-item> <i-input v-model="form.mail"></i-input> </i-form-item> </i-form></pre><p><span style="text-wrap: nowrap;">Form 要用到数据校验,并在对应的 FormItem 中给出校验失败的提示,校验我们会用到一个开源库[async-validator](</span><a href="https://github.com/yiminghe/async-validator)," style="text-wrap: nowrap;">https://github.com/yiminghe/async-validator),</a></p><p><span style="text-wrap: nowrap;"> 基本主流的组件库都是基于它做的校验。使用它很简单,只需按要求写好一个校验规则就好,比如:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">[ { required: true, message: '邮箱不能为空', trigger: 'blur' }, { type: 'email', message: '邮箱格式不正确', trigger: 'blur' } ]</pre><p><span style="text-wrap: nowrap;">这个代表要校验的数据先判断是否为空(required: true),如果为空,则提示“邮箱不能为空”,触发校验的事件为失焦(trigger: 'blur'),如果第一条满足要求,再进行第二条的验证,判断</span></p><p><span style="text-wrap: nowrap;">是否为邮箱格式(type: 'email')等等,还支持自定义校验规则。更详细的用法可以参看它的文档。</span></p><p><strong><span style="text-wrap: nowrap;">接口设计</span></strong><br/></p><p><span style="text-wrap: nowrap;">我们先使用最新的 Vue CLI 3 创建一个空白的项目(如果你还不清楚 Vue CLI 3 的用法,需要先补习一下了,可以阅读文末的扩展阅读 1),并使用 `vue-router` 插件,同时安装好</span><br/></p><p><span style="text-wrap: nowrap;"> `async-validator` 库。</span></p><p><span style="text-wrap: nowrap;">在 `src/components` 下新建一个 `form` 文件夹,并初始化两个组件 `form.vue` 和 `form-item.vue`,然后初始化项目,配置路由,创建一个页面能够被访问到。</span></p><p><span style="text-wrap: nowrap;">编写一个 Vue.js 组件,最重要的是设计好它的接口,一个 Vue.js 组件的接口来自三个部分:props、slots、events。而 Form 和 FormItem 两个组件主要做数据校验,用不</span></p><p><span style="text-wrap: nowrap;">到 events。Form 的 slot 就是一系列的 FormItem,FormItem 的 slot 就是具体的表单控件,比如输入框 `<i-input>` 。那主要设计的就是 props 了。</span></p><p><span style="text-wrap: nowrap;">在 `Form` 组件中,定义两个 props:</span></p><p><span style="text-wrap: nowrap;">* model:表单控件绑定的数据对象,在校验或重置时会访问该数据对象下对应的表单数据,类型为 Object。</span></p><p><span style="text-wrap: nowrap;">* rules:表单验证规则,即上面介绍的 async-validator 所使用的校验规则,类型为 Object。</span></p><p><span style="text-wrap: nowrap;">在 `FormItem` 组件中,也定义两个 props:</span></p><p><span style="text-wrap: nowrap;">* label:单个表单组件的标签文本,类似原生的 `<label>` 元素,类型为 String。</span></p><p><span style="text-wrap: nowrap;">* prop:对应表单域 Form 组件 model 里的字段,用于在校验或重置时访问表单组件绑定的数据,类型为 String。</span></p><p><span style="text-wrap: nowrap;">定义好 props,就可以写出大概的用例了:</span></p><p><br/></p><pre class="brush:js;toolbar:false"><template> <div> <i-form :model="formValidate" :rules="ruleValidate"> <i-form-item label="用户名" prop="name"> <i-input v-model="formValidate.name"></i-input> </i-form-item> <i-form-item label="邮箱" prop="mail"> <i-input v-model="formValidate.mail"></i-input> </i-form-item> </i-form> </div> </template> <script> import iForm from '../components/form/form.vue'; import iFormItem from '../components/form/form-item.vue'; import iInput from '../components/input/input.vue'; export default { components: { iForm, iFormItem, iInput }, data () { return { formValidate: { name: '', mail: '' }, ruleValidate: { name: [ { required: true, message: '用户名不能为空', trigger: 'blur' } ], mail: [ { required: true, message: '邮箱不能为空', trigger: 'blur' }, { type: 'email', message: '邮箱格式不正确', trigger: 'blur' } ], } } } } </script></pre><p><span style="text-wrap: nowrap;">有两点需要注意的是:</span></p><p><span style="text-wrap: nowrap;">1. 这里的 `<i-input>` 并不是原生的 `<input>` 输入框,而是一个特制的输入框组件,之后会介讲解的功能和代码;</span></p><p><span style="text-wrap: nowrap;">2. `<i-form-item>` 的属性 `prop` 是字符串,所以它前面没有冒号(即不是 `:prop="name"`)。</span></p><p><span style="text-wrap: nowrap;">当前的两个组件只是个框框,还没有实现任何功能,不过万事开头难,定义好接口,剩下的就是补全组件的逻辑,而对于使用者,知道了 props、events、slots,就已经能写出上例的使用代码了</span><span style="text-wrap: nowrap;">到此,Form 和 FormItem 的代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- form.vue --> <template> <form> <slot></slot> </form> </template> <script> export default { name: 'iForm', props: { model: { type: Object }, rules: { type: Object } } } </script></pre><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- form-item.vue --> <template> <div> <label v-if="label">{{ label }}</label> <div> <slot></slot> </div> </div> </template> <script> export default { name: 'iFormItem', props: { label: { type: String, default: '' }, prop: { type: String } } } </script></pre><p><strong><span style="text-wrap: nowrap;">在 Form 中缓存 FormItem 实例</span></strong></p><p><span style="text-wrap: nowrap;">`Form` 组件的核心功能是数据校验,一个 Form 中包含了多个 FormItem,当点击提交按钮时,要逐一对每个 FormItem 内的表单组件校验,而校验是由使用者发起,并通过 `Form` 来调用每</span><br/></p><p><span style="text-wrap: nowrap;">一个 `FormItem` 的验证方法,再将校验结果汇总后,通过 `Form` 返回出去。</span></p><p><span style="text-wrap: nowrap;">因为要在 Form 中逐一调用 FormItem 的验证方法,而 Form 和 FormItem 是独立的,需要预先将 FormItem 的每个实例缓存在 Form 中,这个操作就需要用到第 4 节的组件通信方法。当每个</span><br/></p><p><span style="text-wrap: nowrap;">FormItem 渲染时,将其自身(this)作为参数通过 `dispatch` 派发到 Form 组件中,然后通过一个数组缓存起来;同理当 FormItem 销毁时,将其从 Form 缓存的数组中移除。相关代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// form-item.vue,部分代码省略 import Emitter from '../../mixins/emitter.js'; export default { name: 'iFormItem', mixins: [ Emitter ], // 组件渲染时,将实例缓存在 Form 中 mounted () { // 如果没有传入 prop,则无需校验,也就无需缓存 if (this.prop) { this.dispatch('iForm', 'on-form-item-add', this); } }, // 组件销毁前,将实例从 Form 的缓存中移除 beforeDestroy () { this.dispatch('iForm', 'on-form-item-remove', this); } }</pre><p><span style="text-wrap: nowrap;">注意,Vue.js 的组件渲染顺序是由内而外的,所以 FormItem 要先于 Form 渲染,在 FormItem 的 mounted 触发时,我们向 Form 派发了事件 `on-form-item-add`,并将当前 FormItem 的</span></p><p><span style="text-wrap: nowrap;">实例(this)传递给了 Form,而此时,Form 的 mounted 尚未触发,因为 Form 在最外层,如果在 Form 的 mounted 里监听事件,是不可以的,所以要在其 created 内监听自定义事件,</span></p><p><span style="text-wrap: nowrap;">Form 的 created 要先于 FormItem 的 mounted。所以 Form 的相关代码为:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// form.vue,部分代码省略 export default { name: 'iForm', data () { return { fields: [] }; }, created () { this.$on('on-form-item-add', (field) => { if (field) this.fields.push(field); }); this.$on('on-form-item-remove', (field) => { if (field.prop) this.fields.splice(this.fields.indexOf(field), 1); }); } }</pre><p><span style="text-wrap: nowrap;">定义的数据 `fields` 就是用来缓存所有 FormItem 实例的。</span></p><p><strong><span style="text-wrap: nowrap;">触发校验</span></strong><br/></p><p><span style="text-wrap: nowrap;">Form 支持两种事件来触发校验:</span><br/></p><p><span style="text-wrap: nowrap;">* **blur**:失去焦点时触发,常见的有输入框失去焦点时触发校验;</span><br/></p><p><span style="text-wrap: nowrap;">* **change**:实时输入时触发或选择时触发,常见的有输入框实时输入时触发校验、下拉选择器选择项目时触发校验等。</span></p><p><span style="text-wrap: nowrap;">以上两个事件,都是有具体的表单组件来触发的,我们先来编写一个简单的输入框组件 `i-input`。在 `components` 下新建目录 `input`,并创建文件 `input.vue`:</span><br/></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- input.vue --> <template> <input type="text" :value="currentValue" @input="handleInput" @blur="handleBlur" /> </template> <script> import Emitter from '../../mixins/emitter.js'; export default { name: 'iInput', mixins: [ Emitter ], props: { value: { type: String, default: '' }, }, data () { return { currentValue: this.value } }, watch: { value (val) { this.currentValue = val; } }, methods: { handleInput (event) { const value = event.target.value; this.currentValue = value; this.$emit('input', value); this.dispatch('iFormItem', 'on-form-change', value); }, handleBlur () { this.dispatch('iFormItem', 'on-form-blur', this.currentValue); } } } </script></pre><p><span style="text-wrap: nowrap;">Input 组件中,绑定在 `<input>` 元素上的原生事件 `@input`,每当输入一个字符,都会调用句柄 `handleInput`,并通过 `dispatch` 方法向上级的 FormItem 组件派发自定义事件</span></p><p><span style="text-wrap: nowrap;"> `on-form-change`;同理,绑定的原生事件 `@blur` 会在 input 失焦时触发,并传递事件 `on-form-blur`。</span></p><p><span style="text-wrap: nowrap;">基础组件有了,接下来要做的,是在 FormItem 中监听来自 Input 组件派发的自定义事件。这里可以在 mounted 中监听,因为你的手速远赶不上组件渲染的速度,不过在 created 中监听也是</span></p><p><span style="text-wrap: nowrap;">没任何问题的。相关代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// form-item.vue,部分代码省略 export default { methods: { setRules () { this.$on('on-form-blur', this.onFieldBlur); this.$on('on-form-change', this.onFieldChange); }, }, mounted () { if (this.prop) { this.dispatch('iForm', 'on-form-item-add', this); this.setRules(); } } }</pre><p><span style="text-wrap: nowrap;">通过调用 `setRules` 方法,监听表单组件的两个事件,并绑定了句柄函数 `onFieldBlur` 和 `onFieldChange`,分别对应 blur 和 change 两种事件类型。当 onFieldBlur 或 onFieldChange 函</span></p><p><span style="text-wrap: nowrap;">数触发时,就意味着 FormItem 要对**当前的数据**进行一次校验。当前的数据,指的就是通过表单域 Form 中定义的 props:model,结合当前 FormItem 定义的 props:prop 来确定的数据,</span></p><p><span style="text-wrap: nowrap;">可以回顾上文写过的用例。</span></p><p><span style="text-wrap: nowrap;">因为 FormItem 中只定义了数据源的某个 key 名称(即属性 prop),要拿到 Form 中 model 里的数据,需要用到第 3 节的通信方法 provide / inject。所以在 Form 中,把整个实例(this)向</span></p><p><span style="text-wrap: nowrap;">下提供,并在 FormItem 中注入:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// form.vue,部分代码省略 export default { provide() { return { form : this }; } } // form-item.vue,部分代码省略 export default { inject: ['form'] }</pre><p><span style="text-wrap: nowrap;">准备好这些,接着就是最核心的校验功能了。blur 和 change 事件都会触发校验,它们调用同一个方法,只是参数不同。相关代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// form-item.vue,部分代码省略 import AsyncValidator from 'async-validator'; export default { inject: ['form'], props: { prop: { type: String }, }, data () { return { validateState: '', // 校验状态 validateMessage: '', // 校验不通过时的提示信息 } }, computed: { // 从 Form 的 model 中动态得到当前表单组件的数据 fieldValue () { return this.form.model[this.prop]; } }, methods: { // 从 Form 的 rules 属性中,获取当前 FormItem 的校验规则 getRules () { let formRules = this.form.rules; formRules = formRules ? formRules[this.prop] : []; return [].concat(formRules || []); }, // 只支持 blur 和 change,所以过滤出符合要求的 rule 规则 getFilteredRule (trigger) { const rules = this.getRules(); return rules.filter(rule => !rule.trigger || rule.trigger.indexOf(trigger) !== -1); }, /** * 校验数据 * @param trigger 校验类型 * @param callback 回调函数 */ validate(trigger, callback = function () {}) { let rules = this.getFilteredRule(trigger); if (!rules || rules.length === 0) { return true; } // 设置状态为校验中 this.validateState = 'validating'; // 以下为 async-validator 库的调用方法 let descriptor = {}; descriptor[this.prop] = rules; const validator = new AsyncValidator(descriptor); let model = {}; model[this.prop] = this.fieldValue; validator.validate(model, { firstFields: true }, errors => { this.validateState = !errors ? 'success' : 'error'; this.validateMessage = errors ? errors[0].message : ''; callback(this.validateMessage); }); }, onFieldBlur() { this.validate('blur'); }, onFieldChange() { this.validate('change'); } } }</pre><p><span style="text-wrap: nowrap;">在 FormItem 的 `validate()` 方法中,最终做了两件事:</span></p><p><span style="text-wrap: nowrap;">1. 设置了当前的校验状态 `validateState` 和校验不通过提示信息 `validateMessage`(通过值为空);</span><br/></p><p><span style="text-wrap: nowrap;">2. 将 validateMessage 通过回调 callback 传递给调用者,这里的调用者是 onFieldBlur 和 onFieldChange,它们只传入了第一个参数 `trigger`,callback 并未传入,因此也不会触发回调,而</span></p><p><span style="text-wrap: nowrap;">这个回调主要是给 Form 用的,因为 Form 中可以通过提交按钮一次性校验所有的 FormItem(后文会介绍)这里只是表单组件触发事件时,对当前 FormItem 做校验。</span></p><p><span style="text-wrap: nowrap;">除了校验,还可以对当前数据进行重置。重置是指将表单组件的数据还原到最初绑定的值,而不是清空,因此需要预先缓存一份初始值。同时我们将校验信息也显示在模板中,并加一些样式。相</span><br/></p><p><span style="text-wrap: nowrap;">关代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- form-item.vue,部分代码省略 --> <template> <div> <label v-if="label" :class="{ 'i-form-item-label-required': isRequired }">{{ label }}</label> <div> <slot></slot> <div v-if="validateState === 'error'" class="i-form-item-message">{{ validateMessage }}</div> </div> </div> </template> <script> export default { props: { label: { type: String, default: '' }, prop: { type: String }, }, data () { return { isRequired: false, // 是否为必填 validateState: '', // 校验状态 validateMessage: '', // 校验不通过时的提示信息 } }, mounted () { // 如果没有传入 prop,则无需校验,也就无需缓存 if (this.prop) { this.dispatch('iForm', 'on-form-item-add', this); // 设置初始值,以便在重置时恢复默认值 this.initialValue = this.fieldValue; this.setRules(); } }, methods: { setRules () { let rules = this.getRules(); if (rules.length) { rules.every((rule) => { // 如果当前校验规则中有必填项,则标记出来 this.isRequired = rule.required; }); } this.$on('on-form-blur', this.onFieldBlur); this.$on('on-form-change', this.onFieldChange); }, // 从 Form 的 rules 属性中,获取当前 FormItem 的校验规则 getRules () { let formRules = this.form.rules; formRules = formRules ? formRules[this.prop] : []; return [].concat(formRules || []); }, // 重置数据 resetField () { this.validateState = ''; this.validateMessage = ''; this.form.model[this.prop] = this.initialValue; }, } } </script> <style> .i-form-item-label-required:before { content: '*'; color: red; } .i-form-item-message { color: red; } </style></pre><p><span style="text-wrap: nowrap;">至此,FormItem 代码已经完成,不过它只具有单独校验的功能,也就是说,只能对自己的一个表单组件验证,不能对一个表单域里的所有组件一次性全部校验。而实现全部校验和全部重置的功</span></p><p><span style="text-wrap: nowrap;">能,要在 Form 中完成。</span></p><p><span style="text-wrap: nowrap;">上文已经介绍到,在 `Form` 组件中,预先缓存了全部的 FormItem 实例,自然也能在 Form 中调用它们。通过点击提交按钮全部校验,或点击重置按钮全部重置数据,只需要在 Form 中,逐一</span><br/></p><p><span style="text-wrap: nowrap;">调用缓存的 FormItem 实例中的 `validate` 或 `resetField` 方法。相关代码如下:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// form.vue,部分代码省略 export default { data () { return { fields: [] }; }, methods: { // 公开方法:全部重置数据 resetFields() { this.fields.forEach(field => { field.resetField(); }); }, // 公开方法:全部校验数据,支持 Promise validate(callback) { return new Promise(resolve => { let valid = true; let count = 0; this.fields.forEach(field => { field.validate('', errors => { if (errors) { valid = false; } if (++count === this.fields.length) { // 全部完成 resolve(valid); if (typeof callback === 'function') { callback(valid); } } }); }); }); } }, }</pre><p><span style="text-wrap: nowrap;">虽然说 Vue.js 的 API 只来自 prop、event、slot 这三个部分,但一些场景下,需要通过 `ref` 来访问这个组件,调用它的一些内置方法,比如上面的 `validate` 和 `resetFields` 方法,就需要使</span></p><p><span style="text-wrap: nowrap;">用者来主动调用。</span></p><p><span style="text-wrap: nowrap;">resetFields 很简单,就是通过循环逐一调用 FormItem 的 resetField 方法来重置数据。validate 稍显复杂,它支持两种使用方法,一种是普通的回调,比如:</span><br/></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><template> <div> <i-form ref="form"></i-form> <button @click="handleSubmit">提交</button> </div> </template> <script> export default { methods: { handleSubmit () { this.$refs.form.validate((valid) => { if (valid) { window.alert('提交成功'); } else { window.alert('表单校验失败'); } }) } } } </script></pre><p><span style="text-wrap: nowrap;">同时也支持 Promise,例如:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">handleSubmit () { const validate = this.$refs.form.validate(); validate.then((valid) => { if (valid) { window.alert('提交成功'); } else { window.alert('表单校验失败'); } }) }</pre><p><span style="text-wrap: nowrap;">在 Form 组件定义的 Promise 中,只调用了 resolve(valid),没有调用 reject(),因此不能直接使用 `.catch()` ,不过聪明的你稍作修改,肯定能够支持到!</span></p><p><span style="text-wrap: nowrap;">完整的用例如下:</span><br/></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><template> <div> <h3>具有数据校验功能的表单组件——Form</h3> <i-form ref="form" :model="formValidate" :rules="ruleValidate"> <i-form-item label="用户名" prop="name"> <i-input v-model="formValidate.name"></i-input> </i-form-item> <i-form-item label="邮箱" prop="mail"> <i-input v-model="formValidate.mail"></i-input> </i-form-item> </i-form> <button @click="handleSubmit">提交</button> <button @click="handleReset">重置</button> </div> </template> <script> import iForm from '../components/form/form.vue'; import iFormItem from '../components/form/form-item.vue'; import iInput from '../components/input/input.vue'; export default { components: { iForm, iFormItem, iInput }, data () { return { formValidate: { name: '', mail: '' }, ruleValidate: { name: [ { required: true, message: '用户名不能为空', trigger: 'blur' } ], mail: [ { required: true, message: '邮箱不能为空', trigger: 'blur' }, { type: 'email', message: '邮箱格式不正确', trigger: 'blur' } ], } } }, methods: { handleSubmit () { this.$refs.form.validate((valid) => { if (valid) { window.alert('提交成功'); } else { window.alert('表单校验失败'); } }) }, handleReset () { this.$refs.form.resetFields(); } } } </script></pre><p><span style="text-wrap: nowrap;">项目基于 Vue CLI 3 构建,下载安装依赖后,通过 npm run serve 可访问。</span></p>
<p><span style="text-wrap: nowrap;"><br/></span></p><p><strong><span style="text-wrap: nowrap;">组件的通信 :派发与广播——自行实现 dispatch 和 broadcast 方法</span></strong></p><p><span style="text-wrap: nowrap;">上一讲的 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。然后有两种场景</span></p><p><span style="text-wrap: nowrap;">它不能很好的解决:</span></p><p><span style="text-wrap: nowrap;">* 父组件向子组件(支持跨级)传递数据;</span></p><p><span style="text-wrap: nowrap;">* 子组件向父组件(支持跨级)传递数据。</span></p><p><span style="text-wrap: nowrap;">这种父子(含跨级)传递数据的通信方式,Vue.js 并没有提供原生的 API 来支持,而是推荐使用大型数据状态管理工具 Vuex,而我们之前已经介绍过 Vuex 的场景与在独立组件(或库)中使用</span><br/></p><p><span style="text-wrap: nowrap;">的限制。本小节则介绍一种在父子组件间通信的方法 `dispatch` 和 `broadcast`。</span></p><p><strong><span style="text-wrap: nowrap;">$on 与 $emit</span></strong><br/></p><p><span style="text-wrap: nowrap;">如果您使用过较早的 Vue.js 1.x 版本,肯定对 _$dispatch_ 和 _$broadcast_ 这两个内置的方法很熟悉,不过它们都在 Vue.js 2.x 里废弃了。在正式介绍主角前,我们先看看 `$on` 与 `$emit` 这</span><br/></p><p><span style="text-wrap: nowrap;">两个 API,因为它们是本节内容的基础。</span></p><p><span style="text-wrap: nowrap;">`$emit` 会在**当前组件**实例上触发自定义事件,并传递一些参数给监听器的回调,一般来说,都是在父级调用这个组件时,使用 `@on` 的方式来监听自定义事件的,比如在子组件中触发事件:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// child.vue,部分代码省略 export default { methods: { handleEmitEvent () { this.$emit('test', 'Hello Vue.js'); } } }</pre><p><span style="text-wrap: nowrap;">在父组件中监听由 _child.vue_ 触发的自定义事件 **test**:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- parent.vue,部分代码省略--> <template> <child-component @test="handleEvent"> </template> <script> export default { methods: { handleEvent (text) { console.log(text); // Hello Vue.js } } } </script></pre><p><span style="text-wrap: nowrap;">这里看似是在父组件 _parent.vue_ 中绑定的自定义事件 **test** 的处理句柄,然而事件 test 并不是在父组件上触发的,而是在子组件 _child.vue_ 里触发的,只是通过 `v-on` 在父组件中监听。</span></p><p><span style="text-wrap: nowrap;">既然是子组件自己触发的,那它自己也可以监听到,这就要使用 `$on` 来监听实例上的事件,换言之,组件使用 `$emit` 在自己实例上触发事件,并用 `$on` 监听它。</span></p><p><span style="text-wrap: nowrap;">听起来这种神(sāo)操作有点多此一举,我们不妨先来看个示例:</span><br/></p><p><span style="text-wrap: nowrap;">(也可通过在线链接 [https://run.iviewui.com/ggsomfHM](https://run.iviewui.com/ggsomfHM) 直接运行该示例)</span><br/></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><template> <div> <button @click="handleEmitEvent">触发自定义事件</button> </div> </template> <script> export default { methods: { handleEmitEvent () { // 在当前组件上触发自定义事件 test,并传值 this.$emit('test', 'Hello Vue.js') } }, mounted () { // 监听自定义事件 test this.$on('test', (text) => { window.alert(text); }); } } </script></pre><p><span style="text-wrap: nowrap;">`$on` 监听了自己触发的自定义事件 test,因为有时不确定何时会触发事件,一般会在 `mounted` 或 `created` 钩子中来监听。</span></p><p><span style="text-wrap: nowrap;">仅上面的示例,的确是多此一举的,因为大可在 handleEmitEvent 里直接写 window.alert(text),没必要绕一圈。</span></p><p><span style="text-wrap: nowrap;">之所以多此一举,是因为 handleEmitEvent 是当前组件内的 `<button>` 调用的,如果这个方法不是它自己调用,而是其它组件调用的,那这个用法就大有可为了。</span></p><p><span style="text-wrap: nowrap;">了解了 `$on` 和 `$emit` 的用法后,我们再来看两个“过时的” API。</span></p><p><span style="text-wrap: nowrap;"><strong>Vue.js 1.x 的 $dispatch 与 $broadcast</strong></span></p><p><span style="text-wrap: nowrap;">虽然 Vue.js 1.x 已经成为过去时,但为了充分理解本节通信方法的使用场景,还是有必要来了解一点它的历史。</span></p><p><span style="text-wrap: nowrap;">在 Vue.js 1.x 中,提供了两个方法:`$dispatch` 和 `$broadcast` ,前者用于向上级派发事件,只要是它的父级(一级或多级以上),都可以在组件内通过 `$on` (或 events,2.x 已废弃)监听</span></p><p><span style="text-wrap: nowrap;">到,后者相反,是由上级向下级广播事件的。</span></p><p><span style="text-wrap: nowrap;">来看一个简单的示例:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- 注意:该示例为 Vue.js 1.x 版本 --> <!-- 子组件 --> <template> <button @click="handleDispatch">派发事件</button> </template> <script> export default { methods: { handleDispatch () { this.$dispatch('test', 'Hello, Vue.js'); } } } </script> <!-- 父组件,部分代码省略 --> <template> <child-component></child-component> </template> <script> export default { mounted () { this.$on('test', (text) => { console.log(text); // Hello, Vue.js }); } } </script></pre><p><span style="text-wrap: nowrap;">$broadcast 类似,只不过方向相反。这两种方法一旦发出事件后,任何组件都是可以接收到的,就近原则,而且会在第一次接收到后停止冒泡,除非返回 true。</span></p><p><span style="text-wrap: nowrap;">这两个方法虽然看起来很好用,但是在 Vue.js 2.x 中都废弃了,官方给出的解释是:</span><br/></p><p><span style="text-wrap: nowrap;">因为基于组件树结构的事件流方式有时让人难以理解,并且在组件结构扩展的过程中会变得越来越脆弱。</span><br/></p><p><span style="text-wrap: nowrap;">虽然在业务开发中,它没有 Vuex 这样专门管理状态的插件清晰好用,但对独立组件(库)的开发,绝对是福音。因为独立组件一般层级并不会很复杂,并且剥离了业务,不会变的难以维护。</span><br/></p><p><span style="text-wrap: nowrap;">知道了 _$dispatch_ 和 _$broadcast_ 的前世今生,接下来我们就在 Vue.js 2.x 中自行实现这两个方法。</span><br/></p><p><span style="text-wrap: nowrap;"><strong>自行实现 dispatch 和 broadcast 方法</strong></span><br/></p><p><span style="text-wrap: nowrap;">自行实现的 dispatch 和 broadcast 方法,不能保证跟 Vue.js 1.x 的 _$dispatch_ 和 _$broadcast_ 具有完全相同的体验,但基本功能是一样的,都是解决父子组件(含跨级)间的通信问题。</span><br/></p><p><span style="text-wrap: nowrap;">通过目前已知的信息,我们要实现的 dispatch 和 broadcast 方法,将具有以下功能:</span><br/></p><p><span style="text-wrap: nowrap;">* 在子组件调用 dispatch 方法,向上级指定的组件实例(最近的)上触发自定义事件,并传递数据,且该上级组件已预先通过 `$on` 监听了这个事件;</span><br/></p><p><span style="text-wrap: nowrap;">* 相反,在父组件调用 broadcast 方法,向下级指定的组件实例(最近的)上触发自定义事件,并传递数据,且该下级组件已预先通过 `$on` 监听了这个事件。</span></p><p><span style="text-wrap: nowrap;">实现这对方法的关键点在于,如何正确地向上或向下找到对应的组件实例,并在它上面触发方法。在设计一个新功能(features)时,可以先确定这个功能的 API 是什么,也就是说方法名、参</span><br/></p><p><span style="text-wrap: nowrap;">数、使用样例,确定好 API,再来写具体的代码。</span></p><p><span style="text-wrap: nowrap;">因为 Vue.js 内置的方法,才是以 `$` 开头的,比如 `$nextTick`、`$emit` 等,为了避免不必要的冲突并遵循规范,这里的 dispatch 和 broadcast 方法名前不加 `$`。并且该方法可能在很多组件</span><br/></p><p><span style="text-wrap: nowrap;">中都会使用,复用起见,我们封装在混合(mixins)里。那它的使用样例可能是这样的:</span></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">// 部分代码省略 import Emitter from '../mixins/emitter.js' export default { mixins: [ Emitter ], methods: { handleDispatch () { this.dispatch(); // ① }, handleBroadcast () { this.broadcast(); // ② } } }</pre><p><span style="text-wrap: nowrap;">上例中行 ① 和行 ② 的两个方法就是在导入的混合 **emitter.js** 中定义的,这个稍后我们再讲,先来分析这两个方法应该传入什么参数。一般来说,为了跟 Vue.js 1.x 的方法一致,第一个参数</span></p><p><span style="text-wrap: nowrap;">应当是自定义事件名,比如 “test”,第二个参数是传递的数据,比如 “Hello, Vue.js”,但在这里,有什么问题呢?只通过这两个参数,我们没办法知道要在哪个组件上触发事件,因为自行实</span></p><p><span style="text-wrap: nowrap;">现的这对方法,与 Vue.js 1.x 的原生方法机理上是有区别的。上文说到,实现这对方法的关键点在于准确地**找到组件实例**。那在寻找组件实例上,我们的“惯用伎俩”就是通过遍历来匹配组</span></p><p><span style="text-wrap: nowrap;">件的 `name` 选项,在独立组件(库)里,每个组件的 `name` 值应当是唯一的,name 主要用于递归组件,在后面小节会单独介绍。</span></p><p><span style="text-wrap: nowrap;">先来看下 **emitter.js** 的代码:</span><br/></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false">function broadcast(componentName, eventName, params) { this.$children.forEach(child => { const name = child.$options.name; if (name === componentName) { child.$emit.apply(child, [eventName].concat(params)); } else { broadcast.apply(child, [componentName, eventName].concat([params])); } }); } export default { methods: { dispatch(componentName, eventName, params) { let parent = this.$parent || this.$root; let name = parent.$options.name; while (parent && (!name || name !== componentName)) { parent = parent.$parent; if (parent) { name = parent.$options.name; } } if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); } }, broadcast(componentName, eventName, params) { broadcast.call(this, componentName, eventName, params); } } };</pre><p><span style="text-wrap: nowrap;">因为是用作 mixins 导入,所以在 methods 里定义的 dispatch 和 broadcast 方法会被混合到组件里,自然就可以用 `this.dispatch` 和 `this.broadcast` 来使用。</span></p><p><span style="text-wrap: nowrap;">这两个方法都接收了三个参数,第一个是组件的 `name` 值,用于向上或向下递归遍历来寻找对应的组件,第二个和第三个就是上文分析的自定义事件名称和要传递的数据。</span><br/></p><p><span style="text-wrap: nowrap;">可以看到,在 dispatch 里,通过 _while_ 语句,不断向上遍历更新当前组件(即上下文为当前调用该方法的组件)的父组件实例(变量 parent 即为父组件实例),直到匹配到定义的</span><br/></p><p><span style="text-wrap: nowrap;"> `componentName` 与某个上级组件的 `name` 选项一致时,结束循环,并在找到的组件实例上,调用 `$emit` 方法来触发自定义事件 `eventName`。broadcast 方法与之类似,只不过是向下</span></p><p><span style="text-wrap: nowrap;">遍历寻找。</span></p><p><span style="text-wrap: nowrap;">来看一下具体的使用方法。有 **A.vue** 和 **B.vue** 两个组件,其中 B 是 A 的子组件,中间可能跨多级,在 A 中向 B 通信:</span><br/></p><p><span style="text-wrap: nowrap;"></span></p><pre class="brush:js;toolbar:false"><!-- A.vue --> <template> <button @click="handleClick">触发事件</button> </template> <script> import Emitter from '../mixins/emitter.js'; export default { name: 'componentA', mixins: [ Emitter ], methods: { handleClick () { this.broadcast('componentB', 'on-message', 'Hello Vue.js'); } } } </script> // B.vue export default { name: 'componentB', created () { this.$on('on-message', this.showMessage); }, methods: { showMessage (text) { window.alert(text); } } }</pre><p><span style="text-wrap: nowrap;">同理,如果是 B 向 A 通信,在 B 中调用 dispatch 方法,在 A 中使用 $on 监听事件即可。</span></p><p><span style="text-wrap: nowrap;">以上就是自行实现的 dispatch 和 broadcast 方法,相比 Vue.js 1.x,有以下不同:</span></p><p><span style="text-wrap: nowrap;">* 需要额外传入组件的 name 作为第一个参数;</span></p><p><span style="text-wrap: nowrap;">* 无冒泡机制;</span></p><p><span style="text-wrap: nowrap;">* 第三个参数传递的数据,只能是一个(较多时可以传入一个对象),而 Vue.js 1.x 可以传入多个参数,当然,你对 emitter.js 稍作修改,也能支持传入多个参数,只是一般场景传入一个对象</span></p><p><span style="text-wrap: nowrap;">足以。</span></p><p><br/></p>
<p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在Vue 3中,nextTick是一个重要的工具方法,用于在DOM更新周期结束后执行回调。与Vue 2不同的是,Vue 3中的nextTick方法已经与响应式系统的实现紧密相关。在本文中,我们将探讨Vue 3中nextTick的响应式实现原理,以及如何利用这一特性进行高级响应式编程。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">响应式系统的基础<br/>Vue 3中的响应式系统是基于ES6的Proxy对象实现的。在Vue 3中,每个组件实例都会有一个对应的响应式代理对象。当访问组件实例的属性时,实际上是在访问这个代理对象的属性。代理对象会在访问时自动收集相关依赖,并在属性值变化时触发更新。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">例如,下面是一个简单的组件示例:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 13.6px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;"><template> <div>{{ message }}</div> </template> <script> export default { data() { return { message: 'Hello World!' } } } </script></pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在这个组件中,message属性是响应式的。当message的值发生变化时,组件的DOM也会自动更新。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在内部实现上,Vue 3使用了一种名为Reactivity的模块来处理代理对象的创建和更新。Reactivity模块包含了如下几个重要的函数:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">reactive:用于创建一个响应式代理对象。<br/>effect:用于创建一个响应式的副作用函数。<br/>track:用于收集依赖。<br/>trigger:用于触发更新。<br/>这些函数共同构成了Vue 3的响应式系统的基础。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">nextTick的实现原理<br/>在Vue 3中,nextTick方法的实现原理与Vue 2不同。在Vue 2中,nextTick的实现基于异步队列的方式,通过将回调函数放入一个队列中,并在下一个tick中执行来实现异步回调。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在Vue 3中,nextTick方法的实现与响应式系统的更新机制紧密相关。nextTick的实现基于effect函数和flush函数。effect函数用于创建一个响应式的副作用函数,可以自动收集响应式依赖,并在依赖变化时自动执行。flush函数用于在DOM更新周期结束后执行回调函数,并触发更新。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在内部实现上,nextTick方法会创建一个effect函数,并将回调函数作为effect函数的副作用函数传入。然后,nextTick方法会将这个effect函数放入一个队列中,并在下一个tick中触发更新。当更新完成后,flush函数会自动执行队列中的所有effect函数,并调用对应的副作用函数,从而实现异步回调。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">具体来说,nextTick方法的实现流程如下:</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">创建一个effect函数,并将回调函数作为副作用函数传入;<br/>将这个effect函数放入一个待执行队列中;<br/>在下一个tick中,调用flush函数;<br/>flush函数会依次执行队列中的effect函数,并调用对应的副作用函数;<br/>当执行完所有的effect函数后,flush函数会触发更新。<br/>需要注意的是,由于nextTick方法的实现基于effect函数和flush函数,因此只有在当前DOM更新周期结束后,才能确保回调函数执行时最新的DOM已经渲染完成。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">利用nextTick进行高级响应式编程<br/>由于nextTick方法的实现基于effect函数和flush函数,因此我们可以利用这一特性进行高级响应式编程。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在Vue 3中,可以通过调用ref函数或reactive函数创建一个响应式的变量。ref函数用于创建一个简单的响应式变量,而reactive函数则用于创建一个复杂的响应式对象。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">例如,我们可以创建一个响应式的计数器变量:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 13.6px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">import { ref } from 'vue' const count = ref(0)</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在这个例子中,count是一个响应式的变量,初始值为0。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">可以通过访问count.value来获取计数器的当前值,并通过修改count.value来改变计数器的值。由于count是一个响应式的变量,因此在修改计数器的值时,Vue 3会自动收集依赖,并在计数器的值变化时自动更新视图。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">接下来,我们可以利用nextTick方法,将回调函数放入异步队列中,并在下一个tick中执行。这样,我们就可以确保回调函数在DOM更新周期结束后执行,并获取到最新的DOM状态。</p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">例如,我们可以通过下面的代码,在计数器值变化时自动更新视图:</p><pre class="prettyprint linenums prettyprinted" style="box-sizing: border-box; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-stretch: normal; font-size: 13.6px; line-height: 1.6; font-family: "YaHei Consolas Hybrid", Consolas, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Helvetica, monospace, monospace; margin-top: 0px; margin-bottom: 16px; overflow: auto; color: rgb(47, 111, 159); background-color: rgb(246, 246, 246); border: 1px solid rgb(238, 238, 238); padding: 10px; border-radius: 3px; overflow-wrap: break-word; text-wrap: wrap;">import { ref, nextTick } from 'vue' const count = ref(0) watch(count, async () => { // 等待下一个tick await nextTick() // 更新视图 console.log(count.value) })</pre><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap;">在这个例子中,我们使用了watch函数来监听计数器值的变化。当计数器值变化时,我们通过调用nextTick方法,将更新视图的回调函数放入异步队列中。这样,我们就可以确保回调函数在DOM更新周期结束后执行,并获取到最新的DOM状态。</p><p style="box-sizing: border-box; margin-top: 0px; color: rgb(77, 82, 89); font-family: "Microsoft YaHei", Helvetica, "Meiryo UI", "Malgun Gothic", "Segoe UI", "Trebuchet MS", Monaco, monospace, Tahoma, STXihei, 华文细黑, STHeiti, "Helvetica Neue", "Droid Sans", "wenquanyi micro hei", FreeSans, Arimo, Arial, SimSun, 宋体, Heiti, 黑体, sans-serif; text-wrap: wrap; margin-bottom: 0px !important;">小结:<br/>在Vue 3中,nextTick方法已经与响应式系统的实现紧密相关。nextTick方法的实现基于effect函数和flush函数,可以在下一个tick中执行回调函数,并获取到最新的DOM状态。我们可以利用这一特性,进行高级响应式编程,从而更加方便地处理异步回调和更新视图等操作。</p><p><br/></p>