PageSourceSearch

https://zxhfighter.github.io/2017/08/05/primeng-analysis/

html zxhfighter.github.io collected 2026-10-03 10:15:29 UTC 44,477 bytes, 868 lines download raw bytes

1<!DOCTYPE html>
2
3
4
5  
6
7
8<html class="theme-next pisces use-motion" lang="zh-Hans">
9<head>
10  <meta charset="UTF-8"/>
11<meta http-equiv="X-UA-Compatible" content="IE=edge" />
12<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
13
14
15
16
17
18
19
20
21
22<meta http-equiv="Cache-Control" content="no-transform" />
23<meta http-equiv="Cache-Control" content="no-siteapp" />
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39  
40  
41  <link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css" />
42
43
44
45
46  
47  
48  
49  
50
51  
52    
53    
54  
55
56  
57
58  
59
60  
61
62  
63
64  
65    
66    
67    <link href="//fonts.googleapis.com/css?family=Lato:300,300italic,400,400italic,700,700italic&subset=latin,latin-ext" rel="stylesheet" type="text/css">
68  
69
70
71
72
73
74
75<link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css" />
76
77<link href="/css/main.css?v=5.1.1" rel="stylesheet" type="text/css" />
78
79
80  <meta name="keywords" content="primeng," />
81
82
83
84
85
86
87
88
89  <link rel="shortcut icon" type="image/x-icon" href="/favicon.png?v=5.1.1" />
90
91
92
93
94
95
96<meta name="description" content="primeng 是目前市面上一个比较优秀的 Angular 组件库,组件种类多且全,可定制化程度高,文档也写得通俗易懂。 本文将对 primeng 组件库进行简单分析,抛砖引玉,希望能对编写你自己的组件库有所帮助。 项目结构进入项目目录后,运行 tree -L 1 .(如果没有安装 tree 命令,使用 brew install tree 安装),查看目录结构。 12345678910111213">
97<meta name="keywords" content="primeng">
98<meta property="og:type" content="article">
99<meta property="og:title" content="Angular 组件库 primeng 剖析">
100<meta property="og:url" content="http://yoursite.com/2017/08/05/primeng-analysis/index.html">
101<meta property="og:site_name" content="前端花园">
102<meta property="og:description" content="primeng 是目前市面上一个比较优秀的 Angular 组件库,组件种类多且全,可定制化程度高,文档也写得通俗易懂。 本文将对 primeng 组件库进行简单分析,抛砖引玉,希望能对编写你自己的组件库有所帮助。 项目结构进入项目目录后,运行 tree -L 1 .(如果没有安装 tree 命令,使用 brew install tree 安装),查看目录结构。 12345678910111213">
103<meta property="og:locale" content="zh-Hans">
104<meta property="og:updated_time" content="2017-08-05T04:32:19.000Z">
105<meta name="twitter:card" content="summary">
106<meta name="twitter:title" content="Angular 组件库 primeng 剖析">
107<meta name="twitter:description" content="primeng 是目前市面上一个比较优秀的 Angular 组件库,组件种类多且全,可定制化程度高,文档也写得通俗易懂。 本文将对 primeng 组件库进行简单分析,抛砖引玉,希望能对编写你自己的组件库有所帮助。 项目结构进入项目目录后,运行 tree -L 1 .(如果没有安装 tree 命令,使用 brew install tree 安装),查看目录结构。 12345678910111213">
108
109
110
111<script type="text/javascript" id="hexo.configurations">
112  var NexT = window.NexT || {};
113  var CONFIG = {
114    root: '/',
115    scheme: 'Pisces',
116    sidebar: {"position":"left","display":"post","offset":12,"offset_float":0,"b2t":false,"scrollpercent":false,"onmobile":false},
117    fancybox: true,
118    motion: true,
119    duoshuo: {
120      userId: '0',
121      author: '博主'
122    },
123    algolia: {
124      applicationID: '',
125      apiKey: '',
126      indexName: '',
127      hits: {"per_page":10},
128      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
129    }
130  };
131</script>
131
132
133
134
135  <link rel="canonical" href="http://yoursite.com/2017/08/05/primeng-analysis/"/>
136
137
138
139
140
141<script>
142var _hmt = _hmt || [];
143(function() {
144  var hm = document.createElement("script");
145  hm.src = "https://hm.baidu.com/hm.js?9b56b7702f31d1fe7fab8b57548b41de";
146  var s = document.getElementsByTagName("script")[0]; 
147  s.parentNode.insertBefore(hm, s);
148})();
149</script>
149
150
151  <title>Angular 组件库 primeng 剖析 | 前端花园</title>
152  
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167</head>
168
169<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">
170
171  
172  
173    
174  
175
176  <div class="container sidebar-position-left page-post-detail ">
177    <div class="headband"></div>
178
179    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
180      <div class="header-inner"><div class="site-brand-wrapper">
181  <div class="site-meta ">
182    
183
184    <div class="custom-logo-site-title">
185      <a href="/"  class="brand" rel="start">
186        <span class="logo-line-before"><i></i></span>
187        <span class="site-title">前端花园</span>
188        <span class="logo-line-after"><i></i></span>
189      </a>
190    </div>
191      
192        <p class="site-subtitle">frontend garden</p>
193      
194  </div>
195
196  <div class="site-nav-toggle">
197    <button>
198      <span class="btn-bar"></span>
199      <span class="btn-bar"></span>
200      <span class="btn-bar"></span>
201    </button>
202  </div>
203</div>
204
205<nav class="site-nav">
206  
207
208  
209    <ul id="menu" class="menu">
210      
211        
212        <li class="menu-item menu-item-home">
213          <a href="/" rel="section">
214            
215              <i class="menu-item-icon fa fa-fw fa-home"></i> <br />
216            
217            首页
218          </a>
219        </li>
220      
221        
222        <li class="menu-item menu-item-archives">
223          <a href="/archives/" rel="section">
224            
225              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br />
226            
227            归档
228          </a>
229        </li>
230      
231        
232        <li class="menu-item menu-item-tags">
233          <a href="/tags/" rel="section">
234            
235              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br />
236            
237            标签
238          </a>
239        </li>
240      
241
242      
243    </ul>
244  
245
246  
247</nav>
248
249
250
251 </div>
252    </header>
253
254    <main id="main" class="main">
255      <div class="main-inner">
256        <div class="content-wrap">
257          <div id="fullscreen">
258            <i class="fa fa-arrows-alt" aria-hidden="true"></i>
259            &nbsp;&nbsp;<span id="fullscreen-text">全屏阅读</span>
260          </div>
261          <div id="content" class="content">
262            
263
264  <div id="posts" class="posts-expand">
265    
266
267  
268
269  
270  
271  
272
273  <article class="post post-type-normal " itemscope itemtype="http://schema.org/Article">
274    <link itemprop="mainEntityOfPage" href="http://yoursite.com/2017/08/05/primeng-analysis/">
275
276    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
277      <meta itemprop="name" content="zxhfighter">
278      <meta itemprop="description" content="">
279      <meta itemprop="image" content="/images/avatar.gif">
280    </span>
281
282    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
283      <meta itemprop="name" content="前端花园">
284    </span>
285
286    
287      <header class="post-header">
288
289        
290        
291          <h1 class="post-title" itemprop="name headline">Angular 组件库 primeng 剖析</h1>
292        
293
294        <div class="post-meta">
295          <span class="post-time">
296            
297              <span class="post-meta-item-icon">
298                <i class="fa fa-calendar-o"></i>
299              </span>
300              
301                <span class="post-meta-item-text">发表于</span>
302              
303              <time title="创建于" itemprop="dateCreated datePublished" datetime="2017-08-05T00:00:00+08:00">
304                2017-08-05
305              </time>
306            
307
308            
309
310            
311          </span>
312
313          
314            <span class="post-category" >
315            
316              <span class="post-meta-divider">|</span>
317            
318              <span class="post-meta-item-icon">
319                <i class="fa fa-folder-o"></i>
320              </span>
321              
322                <span class="post-meta-item-text">分类于</span>
323              
324              
325                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
326                  <a href="/categories/angular/" itemprop="url" rel="index">
327                    <span itemprop="name">angular</span>
328                  </a>
329                </span>
330
331                
332                
333                  , 
334                
335              
336                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
337                  <a href="/categories/angular/primeng/" itemprop="url" rel="index">
338                    <span itemprop="name">primeng</span>
339                  </a>
340                </span>
341
342                
343                
344              
345            </span>
346          
347
348          
349            
350          
351
352          
353          
354
355          
356
357          
358
359          
360
361        </div>
362      </header>
363    
364
365    <div class="post-body" itemprop="articleBody">
366
367      
368      
369
370      
371        <p><a href="http://primefaces.org/primeng/" target="_blank" rel="external">primeng</a> 是目前市面上一个比较优秀的 Angular 组件库,组件种类多且全,可定制化程度高,文档也写得通俗易懂。</p>
372<p>本文将对 primeng 组件库进行简单分析,抛砖引玉,希望能对编写你自己的组件库有所帮助。</p>
373<h2 id="项目结构"><a href="#项目结构" class="headerlink" title="项目结构"></a>项目结构</h2><p>进入项目目录后,运行 <code>tree -L 1 .</code>(如果没有安装 <code>tree</code> 命令,使用 <code>brew install tree</code> 安装),查看目录结构。</p>
374<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line">$ tree -L 1 .</div><div class="line">.</div><div class="line">├── .angular-cli.json      --- angular-cli 配置文件</div><div class="line">├── LICENSE.md             --- 使用 MIT LICENSE</div><div class="line">├── README.md              --- README</div><div class="line">├── e2e                    --- 基于 Protractor 的集成(端到端)测试,包括几个基础组件</div><div class="line">├── gulpfile.js            --- 使用 gulp 来处理一些 css 和 image 资源</div><div class="line">├── karma.conf.js          --- karma 测试配置文件</div><div class="line">├── package.json           --- package.json</div><div class="line">├── primeng.d.ts           --- 使用 es2015 模块语法导出所有组件中定义的对象</div><div class="line">├── primeng.js             --- 使用 commonjs 模块语法导出所有组件中定义的对象</div><div class="line">├── protractor.conf.js     --- e2e 集成测试配置文件,会运行 e2e 中定义的测试 case</div><div class="line">├── src                    --- 源目录</div><div class="line">├── tsconfig-aot.json      --- 编译配置文件,使用 aot 构建,暂时没有看到使用的地方</div><div class="line">├── tsconfig-release.json  --- 编译配置文件,暂时没有看到使用的地方</div><div class="line">├── tsconfig.json          --- 编译基本配置,会被 src 和 e2e 目录下的配置文件所继承(extends)</div><div class="line">└── tslint.json            --- lint 配置</div></pre></td></tr></table></figure>
375<p>可以看出,primeng 项目结构也采用了 angular-cli 搭建,相比 angular-cli 初始化的项目,多了如下四个文件:</p>
376<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">primeng.d.ts</div><div class="line">primeng.js</div><div class="line">tsconfig-aot.json</div><div class="line">tsconfig-release.json</div></pre></td></tr></table></figure>
377<p>不过暂时没有看到 <code>tsconfig-aot.json</code> 和 <code>tsconfig-release.json</code> 两个编译配置文件用在何处。</p>
378<p>再来看下 src 目录下的文件:</p>
379<figure class="highlight plain"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line">$ tree -L 2 .</div><div class="line"></div><div class="line">.</div><div class="line">├── app</div><div class="line">│   ├── components            --- 组件库,每个组件一个模块</div><div class="line">│   └── showcase              --- demo库</div><div class="line">├── assets                    --- 全局资源,包括图片(images)和主题样式(themes)</div><div class="line">│   ├── components            --- 组件库用到的资源</div><div class="line">│   └── showcase              --- demo库用到的资源</div><div class="line">├── environments              --- 环境变量配置</div><div class="line">│   ├── environment.prod.ts   --- 生成环境变量配置</div><div class="line">│   └── environment.ts        --- 开发环境变量配置</div><div class="line">├── favicon.png</div><div class="line">├── index.html                --- 主页</div><div class="line">├── main.ts                   --- 入口文件</div><div class="line">├── polyfills.ts              --- polyfills,包括 core-js、zone.js、intl、web-animations-js 等</div><div class="line">├── styles.css                --- 全局样式</div><div class="line">├── test.ts                   --- 测试入口文件</div><div class="line">├── tsconfig.app.json         --- 主项目编译文件</div><div class="line">├── tsconfig.spec.json        --- 测试编译文件</div><div class="line">├── typings.d.ts              --- 自定义类型</div><div class="line">└── upload.php                --- 上传处理页</div></pre></td></tr></table></figure>
380<h2 id="组件设计"><a href="#组件设计" class="headerlink" title="组件设计"></a>组件设计</h2><p>组件的代码位于 <code>src/app/components</code> 目录中,组件的一些设计思路如下:</p>
381<ul>
382<li><strong>一个组件一个模块</strong></li>
383</ul>
384<p>这样可以很方便的按需引入组件,也利于组件的开发和维护ã€
384‚</p>
385<p>另外,为了方便,在一个文件中定义了多个组件(一般是该组件的一些依赖组件),以及该包含该组件的模块。</p>
386<ul>
387<li>组件样式<strong>全局引入</strong></li>
388</ul>
389<p>组件样式不在组件中单独引入,那样会给所有组件样式添加默认的 scope 限定(<code>encapsulation = ViewEncapsulation.Emulated</code>),如果外层需要覆盖内层组件样式,会很不方便。因此组件的样式全部在 <code>src/styles.css</code> 中引入。当然也可以将 <code>encapsulation</code> 设置成 <code>ViewEncapsulation.None</code> 来避免 scope 限定,这两种方式二选一即可。</p>
390<p><code>styles.css</code> 内容如下:</p>
391<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">@<span class="keyword">import</span> <span class="string">'assets/showcase/css/primeng.css'</span>;</div><div class="line">@<span class="keyword">import</span> <span class="string">'assets/showcase/css/code.css'</span>;</div><div class="line">@<span class="keyword">import</span> <span class="string">'assets/showcase/css/site.css'</span>;</div></pre></td></tr></table></figure>
392<p><code>assets/showcase/css/primeng.css</code> 文件引入了所有 components 的样式。</p>
393<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div></pre></td><td class="code"><pre><div class="line">@<span class="keyword">import</span> <span class="string">'../../../app/components/common/common.css'</span>;</div><div class="line">@<span class="keyword">import</span> <span class="string">'../../../app/components/autocomplete/autocomplete.css'</span>;</div><div class="line">@<span class="keyword">import</span> <span class="string">'../../../app/components/accordion/accordion.css'</span>;</div><div class="line"><span class="comment">/* ... */</span></div></pre></td></tr></table></figure>
394<ul>
395<li>全部内联模板</li>
396</ul>
397<p>primeng 全部将模板写成了内联模板,优点是文件内容紧凑,不会分散注意力;缺点就是缺乏语法高亮,编写HTML模板无法使用 emmet 等自动语法提示。</p>
398<p>在组件库中,有两个文件夹值得特别注意。</p>
399<h3 id="common-文件夹"><a href="#common-文件夹" class="headerlink" title="common 文件夹"></a>common 文件夹</h3><p>在 <code>common.css</code> 中定义了通用样式,例如 <code>.ui-widget</code>、<code>.ui-helper-reset</code>等,这些通用样式对于更换主题意义重大。</p>
400<p>此外,其余大部分文件定义了组件库使用的一些全局性类型接口,例如广泛使用的 <code>menuitem</code> 结构。</p>
401<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// menuitem.ts</span></div><div class="line"><span class="keyword">export</span> interface MenuItem &#123;</div><div class="line">    label?: string;</div><div class="line">    icon?: string;</div><div class="line">    command?: <span class="function">(<span class="params">event?: any</span>) =&gt;</span> <span class="keyword">void</span>;</div><div class="line">    url?: string;</div><div class="line">    routerLink?: any;</div><div class="line">    items?: MenuItem[];</div><div class="line">    expanded?: boolean;</div><div class="line">    disabled?: boolean;</div><div class="line">    visible?: boolean;</div><div class="line">    target?: string;</div><div class="line">    routerLinkActiveOptions?: any;</div><div class="line">    separator?: boolean;</div><div class="line">    badge?: string;</div><div class="line">    badgeStyleClass?: string;</div><div class="line">    style?:any;</div><div class="line">    styleClass?:string;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
402<p>另外,在 <code>shared.ts</code> 中,定义了一些通用的模板组件,例如 <code>p-header</code>、<code>p-column</code>、<code>p-templateLoader</code> 等。</p>
403<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// shared.ts</span></div><div class="line">@Component(&#123;</div><div class="line">    selector: <span class="string">'p-header'</span>,</div><div class="line">    template: <span class="string">'&lt;ng-content&gt;&lt;/ng-content&gt;'</span></div><div class="line">&#125;)</div><div class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Header</span> </span>&#123;&#125;</div><div class="line"></div><div class="line">@Component(&#123;</div><div class="line">    selector: <span class="string">'p-footer'</span>,</div><div class="line">    template: <span class="string">'&lt;ng-content&gt;&lt;/ng-content&gt;'</span></div><div class="line">&#125;)</div><div class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Footer</span> </span>&#123;&#125;</div><div class="line"></div><div class="line"><span class="comment">
403// ...</span></div></pre></td></tr></table></figure>
404<h3 id="dom-文件夹"><a href="#dom-文件夹" class="headerlink" title="dom 文件夹"></a>dom 文件夹</h3><p>尽管不推荐直接操作 dom,但是对于一个组件库来说,操作 dom 是无法避免的,因此 <code>domhandler.ts</code> 文件封装了大部分 dom 操作。</p>
405<ul>
406<li><code>addClass</code></li>
407<li><code>addMultipleClasses</code></li>
408<li><code>removeClass</code></li>
409<li><code>hasClass</code></li>
410<li><code>siblings</code></li>
411<li><code>find</code></li>
412<li><code>findSingle</code></li>
413<li><code>index</code></li>
414<li><code>relativePosition</code></li>
415<li><code>absolutePosition</code></li>
416<li><code>getHiddenElementOuterHeight</code></li>
417<li><code>getHiddenElementOuterWidth</code></li>
418<li><code>getHiddenElementDimensions</code></li>
419<li><code>scrollInView</code></li>
420<li><code>fadeIn</code></li>
421<li><code>fadeOut</code></li>
422<li><code>getWindowScrollTop</code></li>
423<li><code>getWindowScrollLeft</code></li>
424<li><code>matches</code></li>
425<li><code>getOuterWidth</code></li>
426<li><code>getHorizontalPadding</code></li>
427<li><code>getHorizontalMargin</code></li>
428<li><code>innerWidth</code></li>
429<li><code>width</code></li>
430<li><code>getInnerHeight</code></li>
431<li><code>getOuterHeight</code></li>
432<li><code>getHeight</code></li>
433<li><code>getWidth</code></li>
434<li><code>getViewport</code></li>
435<li><code>getOffset</code></li>
436<li><code>getUserAgent</code></li>
437<li><code>isIE</code></li>
438<li><code>appendChild</code></li>
439<li><code>removeChild</code></li>
440<li><code>isElement</code></li>
441<li><code>calculateScrollbarWidth</code></li>
442<li><code>invokeElementMethod</code></li>
443<li><code>clearSelection</code></li>
444</ul>
445<p>看到这么一大串方法列表,有人会疑惑,这不就是提取了 jQuery 的一部分功能吗,为什么不直接引入 jQuery 呢?</p>
446<p>这里就涉及到一个库的设计原则:<strong>组件库的设计应该纯粹,能够拿来开箱即用,而不用再去配置组件库的一些依赖</strong>。</p>
447<p>如果要引入 jQuery,如果使用 es2015 的模块按需引用,那么需要手动去配置 jQuery 依赖;如果采取全量引入,那就需要在构建时将 jQuery 代码打包到最终的构建输出中,这并不是一个很好的设计方案。</p>
448<p>因此,这里自己实现了一个 jQuery 的 mini 集合来操作 dom。</p>
449<h3 id="组件例子"><a href="#组件例子" class="headerlink" title="组件例子"></a>组件例子</h3><p>以组件 accordion 为例。</p>
450<figure class="highlight js"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// accordion.ts</span></div><div class="line"><span class="comment">// import list</span></div><div class="line"></div><div class="line">@Component(&#123;</div><div class="line">    selector: <span class="string">'p-accordion'</span>,</div><div class="line">    template: <span class="string">`</span></div><div class="line"><span class="string">        &lt;div [ngClass]="'ui-accordion ui-widget ui-helper-reset'" [ngStyle]="style" [class]="styleClass"&gt;</span></div><div class="line"><span class="string">            &lt;ng-content&gt;&lt;/ng-content&gt;</span></div><div class="line"><span class="string">        &lt;/div&gt;</span></div><div class="line"><span class="string">    `</span>,</div><div class="line">&#125;)</div><div class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">Accordion</span> <span class="title">implements</span> <span class="title">BlockableUI</span> </span>&#123;</div><div class="line">    <span class="comment">
450// ...</span></div><div class="line">&#125;</div><div class="line"></div><div class="line">@Component(&#123;</div><div class="line">    selector: <span class="string">'p-accordionTab'</span>,</div><div class="line">    template: <span class="string">`</span></div><div class="line"><span class="string">        &lt;div class="ui-accordion-header"&gt;</span></div><div class="line"><span class="string">        &lt;/div&gt;</span></div><div class="line"><span class="string">        &lt;div class="ui-accordion-content-wrapper"&gt;</span></div><div class="line"><span class="string">        &lt;/div&gt;</span></div><div class="line"><span class="string">    `</span></div><div class="line">    <span class="comment">// ...</span></div><div class="line">&#125;)</div><div class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">AccordionTab</span> <span class="title">implements</span> <span class="title">OnDestroy</span> </span>&#123;</div><div class="line">    <span class="comment">// ...</span></div><div class="line">&#125;</div><div class="line"></div><div class="line">@NgModule(&#123;</div><div class="line">    imports: [CommonModule],</div><div class="line">    exports: [Accordion,AccordionTab],</div><div class="line">    declarations: [Accordion,AccordionTab]</div><div class="line">&#125;)</div><div class="line"><span class="keyword">export</span> <span class="class"><span class="keyword">class</span> <span class="title">AccordionModule</span> </span>&#123; &#125;</div></pre></td></tr></table></figure>
451<p>文件中定义了一个模块 <code>AccordionModule</code>,容器组件 <code>p-accordion</code>,以及面板组件 <code>p-accordionTab</code>。当然也可以分为三个文件去定义组件和模块,这两种代码组织方式也是仁者见仁,智者见智的问题。</p>
452<h2 id="主题样式"><a href="#主题样式" class="headerlink" title="主题样式"></a>主题样式</h2><p>primeng 的主题样式采取了组件结构层样式(css)和è
452¡¨çŽ°å±‚æ ·å¼ï¼ˆscss)分离的策略,也即:</p>
453<ul>
454<li>结构层样式:只定义组件的结构相关的属性,例如 box-model 相关属性 <code>display</code>,<code>position</code>,<code>padding</code>,<code>margin</code>等</li>
455<li>表现层样式:定义组件展现的外观属性,例如 <code>border</code>,<code>color</code>,<code>background</code>,<code>transition</code>,<code>outline</code>,<code>box-shadow</code>等</li>
456</ul>
457<p>以 Button 为例,在 <code>src/app/components/button/button.css</code> 中,定义了按钮结构层相关样式。</p>
458<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/* Button */</span></div><div class="line"><span class="selector-class">.ui-button</span> &#123;</div><div class="line">    <span class="attribute">display</span>: inline-block;</div><div class="line">    <span class="attribute">position</span>: relative;</div><div class="line">    <span class="attribute">padding</span>: <span class="number">0</span>;</div><div class="line">    <span class="attribute">margin-right</span>: .<span class="number">1em</span>;</div><div class="line">    <span class="attribute">text-decoration</span>: none <span class="meta">!important</span>;</div><div class="line">    <span class="attribute">cursor</span>: pointer;</div><div class="line">    <span class="attribute">text-align</span>: center;</div><div class="line">    <span class="attribute">zoom</span>: <span class="number">1</span>;</div><div class="line">    <span class="attribute">overflow</span>: visible; <span class="comment">/* the overflow property removes extra width in IE */</span></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="selector-class">.ui-button-icon-only</span> &#123;</div><div class="line">    <span class="attribute">width</span>: <span class="number">2em</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">/*button text element */</span></div><div class="line"><span class="selector-class">.ui-button</span> <span class="selector-class">.ui-button-text</span> &#123;</div><div class="line">    <span class="attribute">display</span>: block;</div><div class="line">    <span class="attribute">line-height</span>: normal;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
459<p>在 <code>src/assets/components/themes/_theme.scss</code> 中,定义了组件的一些基础表现层样式,例如所有的组件都包含有 <code>ui-widget</code> 类,该类定义如下:</p>
460<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="selector-class">.ui-widget</span> &#123;</div><div class="line">    <span class="attribute">font-family</span>:  $fontFamily;</div><div class="line">    <span class="attribute">font-size</span>: $fontSize;
460</div><div class="line"></div><div class="line">    input, select, textarea, button &#123;</div><div class="line">        font-family:  $fontFamily;</div><div class="line">        font-size: $fontSize;</div><div class="line">    &#125;</div><div class="line"></div><div class="line">    <span class="selector-pseudo">:active</span> &#123;</div><div class="line">        <span class="attribute">outline</span>: none;</div><div class="line">    &#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="selector-class">.ui-widget-content</span> &#123;</div><div class="line">    <span class="attribute">border</span>: $contentBorderWidth solid $contentBorderColor;</div><div class="line">    <span class="attribute">background</span>: $contentBgColor;</div><div class="line">    <span class="attribute">color</span>: $contentTextColor;</div><div class="line"></div><div class="line">    a &#123;</div><div class="line">        color: $contentTextColor;</div><div class="line">    &#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
461<p>这两个样式类定义了所有组件的通用表现样式,例如字体、边框、背景色、前景色、链接颜色等。</p>
462<p>其中的变量,例如 <code>$fontFamily</code>,<code>$contentBorderWidth</code> 则在主题文件中去定义,primeng 提供了相当多的主题,你也可以很轻松的自定义自己的主题。</p>
463<p>例如,看下主题 <code>cruze</code> 的样式实现。</p>
464<figure class="highlight css"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div></pre></td><td class="code"><pre><div class="line"><span class="comment">/* src/assets/components/themes/cruze/theme.scss */</span></div><div class="line"></div><div class="line">$fontFamily: Segoe UI, Arial, sans-serif;</div><div class="line">$fontSize: 1em;</div><div class="line">$borderRadius: 6px;</div><div class="line">$disabledOpacity: 0.35;</div><div class="line"></div><div class="line">//Content</div><div class="line">$contentBorderWidth: 1px;</div><div class="line">$contentBorderColor: #dddddd;</div><div class="line">$contentBgColor: #ffffff;</div><div class="line">$contentTextColor: #444444;</div><div class="line"></div><div class="line"><span class="comment">/* ... */</span></div><div class="line"></div><div class="line">@<span class="keyword">import</span> <span class="string">'../_theme'</span>;</div></pre></td></tr></table></figure>
465<p>你也可以写一个自己的主题配置文件来实现轻松换肤的要求。</p>
466<h2 id="文档"><a href="#文档" class="headerlink" title="文档"></a>文档</h2><p>文档就是 <code>src/app/showcase</code> 模块,在该模块中引入了 <code>src/app/components</code> 中的组件,编写相应的帮助文档。</p>
467<h2 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h2><p>primeng 暂时没有包含组件单元测试,只有在 e2e 文件夹有几个集成测试。</p>
468<p>个人建议如果时间精力足够的话,每个组件还是需要写上单测。</p>
469<p>后续有时间,会抽出几个有代表性的组件进行分析,敬请期待。</p>
470
471      
472    </div>
473
474    <div>
475      
476        
477
478      
479    </div>
480
481    <div>
482      
483        
484  <div style="padding: 10px 0; margin: 20px auto; width: 90%; text-align: center;">
485    <div>坚持原创技术分享,您的支持将让我在冬天有冰棍吃啦,^_^!</div>
486    <button id="rewardButton" disable="enable" onclick="var qr = document.getElementById('QR'); if (qr.style.display === 'none') {qr.style.display='block';} else {qr.style.display='none'}">
487      <span>赏</span>
488    </button>
489    <div id="QR" style="display: none;">
490      
491        <div id="wechat" style="display: inline-block">
492          <img id="wechat_qr" src="http://otwtmlrnk.bkt.clouddn.com/%E5%BE%AE%E4%BF%A1%E8%BD%AC%E8%B4%A6.jpeg" alt="zxhfighter WeChat Pay"/>
493          <p>微信打赏</p>
494        </div>
495      
496      
497        <div id="alipay" style="display: inline-block">
498          <img id="alipay_qr" src="http://otwtmlrnk.bkt.clouddn.com/%E6%94%AF%E4%BB%98%E5%AE%9D%E8%BD%AC%E8%B4%A6.jpeg" alt="zxhfighter Alipay"/>
499          <p>支付宝打赏</p>
500        </div>
501      
502    </div>
503  </div>
504
505
506      
507    </div>
508
509    <div>
510      
511        
512
513      
514    </div>
515
516    <footer class="post-footer">
517      
518        <div class="post-tags">
519          
520            <a href="/tags/primeng/" rel="tag"># primeng</a>
521          
522        </div>
523      
524
525      
526      
527      
528
529      
530        <div class="post-nav">
531          <div class="post-nav-next post-nav-item">
532            
533              <a href="/2017/08/01/webpack-amd/" rel="next" title="用 webpack 构建 AMD 项目">
534                <i class="fa fa-chevron-left"></i> 用 webpack 构建 AMD 项目
535              </a>
536            
537          </div>
538
539          <span class="post-nav-divider"></span>
540
541          <div class="post-nav-prev post-nav-item">
542            
543          </div>
544        </div>
545      
546
547      
548      
549    </footer>
550  </article>
551
552
553
554    <div class="post-spread">
555      
556    </div>
557  </div>
558
559
560          </div>
561          
562
563
564          
565  <div id="container"></div>
566  <link rel="stylesheet" href="https://imsun.github.io/gitment/style/default.css">
567  
567<script src="https://imsun.github.io/gitment/dist/gitment.browser.js"></script>
567
568  
568<script>
569  var gitment = new Gitment({
570    owner: 'zxhfighter',
571    repo: 'zxhfighter.github.io',
572    oauth: {
573      client_id: '7fc67caf2df967fab029',
574      client_secret: '70769447d9845a485dffda6fd22d08f1028b0525',
575    },
576  })
577  gitment.render('container')
578  </script>
578
579
580
581        </div>
582        
583          
584  
585  <div class="sidebar-toggle">
586    <div class="sidebar-toggle-line-wrap">
587      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
588      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
589      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
590    </div>
591  </div>
592
593  <aside id="sidebar" class="sidebar">
594    
595    <div class="sidebar-inner">
596
597      
598
599      
600        <ul class="sidebar-nav motion-element">
601          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap" >
602            文章目录
603          </li>
604          <li class="sidebar-nav-overview" data-target="site-overview">
605            站点概览
606          </li>
607        </ul>
608      
609
610      <section class="site-overview sidebar-panel">
611        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
612          <img class="site-author-image" itemprop="image"
613               src="/images/avatar.gif"
614               alt="zxhfighter" />
615          <p class="site-author-name" itemprop="name">zxhfighter</p>
616           
617              <p class="site-description motion-element" itemprop="description">frontend, angular, angularjs, typescript, rxjs, spa, ionic, vue, vue.js, react, native react, nativescript</p>
618          
619        </div>
620        <nav class="site-state motion-element">
621
622          
623            <div class="site-state-item site-state-posts">
624              <a href="/archives/">
625                <span class="site-state-item-count">3</span>
626                <span class="site-state-item-name">日志</span>
627              </a>
628            </div>
629          
630
631          
632            
633            
634            <div class="site-state-item site-state-categories">
635              
636                <span class="site-state-item-count">3</span>
637                <span class="site-state-item-name">分类</span>
638              
639            </div>
640          
641
642          
643            
644            
645            <div class="site-state-item site-state-tags">
646              <a href="/tags/index.html">
647                <span class="site-state-item-count">7</span>
648                <span class="site-state-item-name">标签</span>
649              </a>
650            </div>
651          
652
653        </nav>
654
655        
656
657        <div class="links-of-author motion-element">
658          
659        </div>
660
661        
662        
663
664        
665        
666
667        
668
669
670      </section>
671
672      
673      <!--noindex-->
674        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
675          <div class="post-toc">
676
677            
678              
679            
680
681            
682              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#项目结构"><span class="nav-number">1.</span> <span class="nav-text">项目结构</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#组件设计"><span class="nav-number">2.</span> <span class="nav-text">组件设计</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#common-文件夹"><span class="nav-number">2.1.</span> <span class="nav-text">common 文件夹</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#dom-文件夹"><span class="nav-number">2.2.</span> <span class="nav-text">dom 文件夹</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#组件例子"><span class="nav-number">2.3.</span> <span class="nav-text">组件例子</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#主题样式"><span class="nav-number">3.</span> <span class="nav-text">主题样式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#文档"><span class="nav-number">4.</span> <span class="nav-text">文档</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#测试"><span class="nav-number">5.</span> <span class="nav-text">测试</span></a></li></ol></div>
683            
684
685          </div>
686        </section>
687      <!--/noindex-->
688      
689
690      
691
692    </div>
693  </aside>
694
695
696        
697      </div>
698    </main>
699
700    <footer id="footer" class="footer">
701      <div class="footer-inner">
702        <div class="copyright" >
703  
704  &copy; 
705  <span itemprop="copyrightYear">2017</span>
706  <span class="with-love">
707    <i class="fa fa-heart"></i>
708  </span>
709  <span class="author" itemprop="copyrightHolder">zxhfighter</span>
710</div>
711
712
713<div class="powered-by">
714  由 <a class="theme-link" href="https://hexo.io">Hexo</a> 强力驱动
715</div>
716
717<div class="theme-info">
718  主题 -
719  <a class="theme-link" href="https://github.com/iissnan/hexo-theme-next">
720    NexT.Pisces
721  </a>
722</div>
723
724
725        
726
727        
728      </div>
729    </footer>
730
731    
732      <div class="back-to-top">
733        <i class="fa fa-arrow-up"></i>
734        
735      </div>
736    
737
738  </div>
739
740  
741
742<script type="text/javascript">
743  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
744    window.Promise = null;
745  }
746</script>
746
747
748
749
750
751
752
753
754
755
756  
757
758
759
760
761
762
763
764
765
766
767
768
769  
770  
770<script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script>
770
771
772  
773  
773<script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
773
774
775  
776  
776<script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
776
777
778  
779  
779<script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script>
779
780
781  
782  
782<script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
782
783
784  
785  
785<script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
785
786
787
788  
789
790
791  
791<script type="text/javascript" src="/js/src/utils.js?v=5.1.1"></script>
791
792
793  
793<script type="text/javascript" src="/js/src/motion.js?v=5.1.1"></script>
793
794
795
796
797  
798  
799
800
801  
801<script type="text/javascript" src="/js/src/affix.js?v=5.1.1"></script>
801
802
803  
803<script type="text/javascript" src="/js/src/schemes/pisces.js?v=5.1.1"></script>
803
804
805
806
807  
808  
808<script type="text/javascript" src="/js/src/scrollspy.js?v=5.1.1"></script>
vendor: 1 bytes, line 808
808
809<script type="text/javascript" src="/js/src/post-details.js?v=5.1.1"></script>
809
810
811
812
813  
814
815
816  
816<script type="text/javascript" src="/js/src/bootstrap.js?v=5.1.1"></script>
816
817
818
819
820  
821
822
823  
824
825
826
827
828	
829
830
831
832
833
834  
835
836
837
838
839
840  
841
842
843
844
845
846
847  
848
849
850
851
852
853  
854
855  
856
857  
858
859  
860
861  
862
863  
864
865  
865<script type="text/javascript" src="/js/src/screenfull.min.js?v=5.1.1"></script>
865
866
867</body>
868</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.