Angular 项目实现国际化的方法

前端之家收集整理的这篇文章主要介绍了Angular 项目实现国际化的方法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

正如angular官网所说,项目国际化是一件具有挑战性,需要多方面的努力、持久的奉献和决心的任务。 本文将介绍angular项目的国际化方案,涉及静态文件(html)和ts文件文案的国际化。

背景

  1. Angular: 5.0
  2. Angular Cli: 1.6.1(1.5.x也可以)
  3. NG-ZORRO: 0.6.8

Angular i18n

i18n模板翻译流程有四个阶段:

  1. 在组件模板中标记需要翻译的静态文本信息(即打上i18n标签)。
  2. Angular的i18n工具将标记的信息提取到一个行业标准的翻译源文件(如.xlf文件,使用ng xi18n)。
  3. 翻译人员编辑该文件,翻译提取出来的文本信息到目标语言,并将该文件还给你(需要翻译人员接入,本文采用将xlf文件转为json格式文件输出,最终将json文件转换回xlf格式文件)。
  4. Angular编译器导入完成翻译的文件,使用翻译的文本替换原始信息,并生成新的目标语言版本的应用程序。

你可以为每种支持的语言构建和部署单独的项目版本,仅需替换翻译后的xlf文件即可。

如何在模板文件中使用?

i18n提供了几种使用方式,还专门为单复数提供了翻译方式(个人没有使用,感觉不太方便)。接下来以一个单独的html文件来介绍几种使用方法

<Meta charset="utf-8"> Angular i18n@H_<a href="/tag/502/" target="_blank" class="keywords">502</a>_42@ </head> <body> <h1 i18n="Site Header|An introduction header for i18n Project@@stTitle">Angular 国际化项目</h1> <p> <span i18n="@@agDescription">国际化是一项很具有挑战性,需要多方面的努力、持久的奉献和决心的任务。</span> <span class="delete" i18n-title="@@agDelete" title="<a href="/tag/shanchu/" target="_blank" class="keywords">删除</a>"></span> </p> <p><ng-container i18n=@@agLetGo>让我们现在开始吧!</ng-container>朋友!</p> </body> </html> </pre> </div> <p>上述<a href="/tag/daima/" target="_blank" class="keywords">代码</a>展示了几种i18n的使用方式:</p> <p>1、使用i18n<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a><a href="/tag/biaoji/" target="_blank" class="keywords">标记</a>(可<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>上说明性文案,格式如:title|description@@id,title和description可帮助翻译人员更好地理解文案含义,是否<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>取决于自身项目情况) </p> <p>可以在静态<a href="/tag/biaoqian/" target="_blank" class="keywords">标签</a>上直接打上i18n的tag,如 </p> <div class="jb51code"> <pre class="brush:xhtml;"> <span i18n="@@agDescription"></span></pre> </div> <p><a href="/tag/shengcheng/" target="_blank" class="keywords">生成</a>的xlf(xml)字段格式为 </p> <div class="jb51code"> <pre class="brush:xml;"> <trans-unit id="agDescription" datatype="html"> <source>国际化是一项很具有挑战性,需要多方面的努力、持久的奉献和决心的任务。</source> <context-group purpose="location"> <context context-type="sourcefile">xxx.ts</context> <context context-type="linenumber">linenum</context> </context-group> </trans-unit></pre> </div> <p>2、为title<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>i18n<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a> </p> <p>对于html<a href="/tag/biaoqian/" target="_blank" class="keywords">标签</a><a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>,同样可以<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>i18n,如 </p> <div class="jb51code"> <pre class="brush:xhtml;"> <span class="delete" i18n-title="@@agDelete" title="<a href="/tag/shanchu/" target="_blank" class="keywords">删除</a>"></span></pre> </div> <p><a href="/tag/shengcheng/" target="_blank" class="keywords">生成</a>的xlf(xml)格式同上 </p> <p>3、翻译文本,而不必创建元素 </p> <p>我们有时候会出现一句话多个断句情况,如果每次都<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>span、label这些元素包裹的话,可能严重影响<a href="/tag/yemian/" target="_blank" class="keywords">页面</a>布局,这时候我们可以使用ng-container来包裹需要翻译的文案。 </p> <div class="jb51code"> <pre class="brush:xhtml;"> <p> <ng-container i18n=@@agLetGo>让我们现在开始吧!</ng-container>朋友! </p></pre> </div> <p>在<a href="/tag/yemian/" target="_blank" class="keywords">页面</a><a href="/tag/xianshi/" target="_blank" class="keywords">显示</a>为 </p> <div class="jb51code"> <pre class="brush:xhtml;"> <p> <!----> LET'S GO朋友! </p></pre> </div> <p>* ng-container变为了注释块,这样做不会影响<a href="/tag/yemian/" target="_blank" class="keywords">页面</a>布局(尤其是应用了style样式的情况) </p> <p>打上<a href="/tag/biaoqian/" target="_blank" class="keywords">标签</a>后,我们只要执行ng xi18n即可<a href="/tag/zidong/" target="_blank" class="keywords">自动</a>创建出xlf<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>,通常为message.xlf,如需<a href="/tag/zidingyi/" target="_blank" class="keywords">自定义</a>,可自行前往 Angular CLI 官网查看。</p> <p><h3>XLF与JSON转换</h3> </p> <p>xlf转json<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a> </p> <p>我个人是采用xml2js库进行操作,简单<a href="/tag/daima/" target="_blank" class="keywords">代码</a>如下: </p> <div class="jb51code"> <pre class="brush:js;"> const fs = require('fs'); xml2js = require('xml2js'); var parser = new xml2js.Parser(); fs.readFile(fileName,'utf8',(err,data) => { parser.parseString(data,function (err,result) { // 读取新<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>全部需要翻译的数据,并对比已翻译的进行取舍,具体转换成的格式结构可自行查看 result['xliff']['file'][0]['body'][0]['trans-unit'].forEach((item) => { var itemFormat = { "key" : item['$']['id'],"value": item['source'][0] }; // 执行相关操作,key-value形式是为了统一翻译<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>结构,可按需定义 }) }); }); </pre> </div> <p>json转xlf<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a> </p> <div class="jb51code"> <pre class="brush:js;"> function backToXLF(translatedParams) { // 文件格式可自行参考angular.cn官网的例子 var xlfFormat = { "xliff": { "$" : { "version": "1.2","xmlns" : "urn:oasis:names:tc:xliff:document:1.2" },"file": [ { "$" : { "source-language": "en","datatype" : "plaintext","original" : "ng2.template" },"body": [ { "trans-unit": [] } ] } ] } }; if (translatedParams instanceof Array) { // 获取原始名称 translatedParams.forEach((data) => { var tmp = { "$" : { "id" : data.key,"datatype": "html" },"source": [i18nItemsOrigin[data.key]],// 这里的i18nItemsOrigin是json格式,<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>名为key值,表示原始文案 "target": [data.value] }; // 数组,json项 xlfFormat['xliff']['file'][0]['body'][0]['trans-unit'].push(tmp); }); } var builder = new xml2js.Builder(); var xml = builder.buildObject(xlfFormat); return xml; }</pre> </div> <p>这样<a href="/tag/tiqu/" target="_blank" class="keywords">提取</a>文案信息和转换翻译后的<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>就完成了,接下来我们需要把翻译好的文案应用到项目中去。 </p> <h2><h3>部署翻译<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a></h3> </h2> <p>src目录下新建locale<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>夹,将翻译转换后的demo.en-US.xlf<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>存在改目录下 </p> <p>app<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>夹下新建i18n-providers.ts</p> <div class="jb51code"> <pre class="brush:js;"> import { LOCALE_ID,MissingTranslationStrategy,StaticProvider,TRANSLATIONS,TRANSLATIONS_FORMAT } from '@angular/core'; import { CompilerConfig } from '@angular/compiler'; import { Observable } from 'rxjs/Observable'; import { LOCALE_LANGUAGE } from './app.config'; // 自行定义配置位置 <p>export function getTranslationProviders(): Promise<StaticProvider[]> {</p> <p>// get the locale string from the document<br /> const locale = LOCALE_LANGUAGE.toString();</p> <p>// return no providers<br /> const noProviders: StaticProvider[] = [];</p> <p>// no locale or zh-CN: no translation providers<br /> if (!locale || locale === 'zh-CN') {<br /> return Promise.resolve(noProviders);<br /> }</p> <p>// Ex: 'locale/demo.zh-MO.xlf<code> const translationFile =</code>./locale/demo.${locale}.xlf`;</p> <p>return getTranslationsWithSystemJs(translationFile)<br /> .then((translations: string) => [<br /> { provide: TRANSLATIONS,useValue: translations },{ provide: TRANSLATIONS_FORMAT,useValue: 'xlf' },{ provide: LOCALE_ID,useValue: locale },{<br /> provide: CompilerConfig,useValue: new CompilerConfig({ missingTranslation: MissingTranslationStrategy.Error })<br /> }<br /> ]).catch(() => noProviders); // ignore if file not found<br /> }</p> <p>declare var System: any;<br /> // <a href="/tag/huoqu/" target="_blank" class="keywords">获取</a>locale<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a><br /> function getTranslationsWithSystemJs(file: string) {<br /> let text = '';<br /> const fileRequest = new XMLHttpRequest();<br /> fileRequest.open('GET',file,false);<br /> fileRequest.onerror = function (err) {<br /> console.log(err);<br /> };<br /> fileRequest.onreadystatechange = function () {<br /> if (fileRequest.readyState === 4) {<br /> if (fileRequest.status === 200 || fileRequest.status === 0) {<br /> text = fileRequest.responseText;<br /> }<br /> }<br /> };<br /> fileRequest.send();<br /> const observable = Observable.of(text);<br /> const prom = observable.toPromise();<br /> return prom;<br /> }</p> </pre> </div> <p>main.ts<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a><a href="/tag/xiugai/" target="_blank" class="keywords">修改</a>为</p> <div class="jb51code"> <pre class="brush:js;"> import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; <p>import { AppModule } from './app/app.module';<br /> import { environment } from './environments/environment';<br /> import { getTranslationProviders } from './app/i18n-providers';</p> <p>if (environment.production) {<br /> enableProdMode();<br /> }</p> <p>getTranslationProviders().then(providers => {<br /> const options = { providers };<br /> platformBrowserDynamic().bootstrapModule(AppModule,options)<br /> .catch(err => console.log(err));<br /> });</p> </pre> </div> <p>别忘了将locale目录<a href="/tag/tianjia/" target="_blank" class="keywords">添加</a>到.angular-cli.json里,来单独打包。 </p> <p>这样我们对静态文案的翻译工作基本已经完成了,但是有些动态文案如ts<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>里的文案或者第三方框架<a href="/tag/shuxing/" target="_blank" class="keywords">属性</a>该如何翻译呢?下面会介绍针对 ts <a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>和 <a target="_blank" href="https://ng.ant.design/#/docs/angular/introduce" rel="external nofollow" >NG-ZORRO </a>框架实现动态文案翻译的方案。</p> <h2><h3>ts<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>文案和NG-ZORRO框架文案翻译</h3> </h2> <p>具体思路 </p> <p>通过Pipe<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>Service<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>,根据对应的唯一id值匹配json对象里的翻译结果,进而返回渲染到前端,参考于NG-ZORRO框架的国际化实现方案。 </p> <p>首先我们定义一下json翻译对象的格式,全部为三层结构,动态变量需要按%%包裹,这样做的原因是和项目结构相关联,也便于后期和i18n方式格式统一。</p> <div class="jb51code"> <pre class="brush:js;"> { "app": { "base": { "hello": "<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>文案","userCount": "一共%num%人" } } }</pre> </div> <p>格式已定,我们继续定义Service处理方式 </p> <p>这里复用<a target="_blank" href="https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/src/components/locale/nz-locale.service.ts" rel="external nofollow" >NG-ZORRO的国际化方案</a>,可以简化我们的开发,有兴趣的可以参看一下其源码。</p> <div class="jb51code"> <pre class="brush:js;"> *** TranslateService *** import { Injectable } from '@angular/core'; // 引入语言配置和国际化文件文案对象 import { LOCALE_LANGUAGE } from '../app.config'; import { enUS } from '../locales/demo.en-US'; import { zhCN } from '../locales/stream.zh-CN'; <p>@Injectable()<br /> export class TranslateService {</p> <p>private _locale = LOCALE_LANGUAGE.toString() === 'zh-CN' ? zhCN : enUS;</p> <p>constructor() {<br /> }<br /> // path为app.base.hello格式的字符串,这里按json层级取匹配改变量<br /> translate(path: string,data?: any): string {<br /> let content = this._getObjectPath(this._locale,path) as string;<br /> if (typeof content === 'string') {<br /> if (data) {<br /> Object.keys(data).forEach((key) => content = content.replace(new RegExp(<code>%${key}%</code>,'g'),data[key]));<br /> }<br /> return content;<br /> }<br /> return path;<br /> }</p> <p>private _getObjectPath(obj: object,path: string): string | object {<br /> let res = obj;<br /> const paths = path.split('.');<br /> const depth = paths.length;<br /> let index = 0;<br /> while (res && index < depth) {<br /> res = res[paths[index++]];<br /> }<br /> return index === depth ? res : null;<br /> }<br /> }</p> </pre> </div> <p>这样,只需要在Pipe中<a href="/tag/diaoyong/" target="_blank" class="keywords">调用</a>Service的translate<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>即可</p> <div class="jb51code"> <pre class="brush:js;"> *** NzTranslateLocalePipe *** import { Pipe,PipeTransform } from '@angular/core'; import { TranslateService } from '../services/translate.service'; <p>@Pipe({<br /> name: 'nzTranslateLocale'<br /> })<br /> export class NzTranslateLocalePipe implements PipeTransform {<br /> constructor(private _locale: TranslateService) {<br /> }</p> <p>transform(path: string,keyValue?: object): string {<br /> return this._locale.translate(path,keyValue);<br /> }<br /> }</p> </pre> </div> <p>好了,现在我们处理逻辑已经完全结束了,下面介绍一下如何使用</p> <div class="jb51code"> <pre class="brush:js;"> *** NG-ZORRO 控件 *** <nz-input [nzPlaceHolder]="'app.base.hello'|nzTranslateLocale"></nz-input> // 无动态参数 <nz-popconfirm [nzTitle]="'app.base.userCount'|nzTranslateLocale: {num:users.length}" ...> ... // 有动态参数 </nz-popconfirm> <p><strong><em> ts<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a> </em></strong><br /> export class AppComponent implements OnInit {<br /> demoTitle='';<br /> users = ['Jack','Johnson','Lucy'];<br /> constructor(privete translateService: TranslateService) {<br /> }<br /> ngOnInit() {<br /> this.demoTitle = this.translateService.translate('app.base.hello');<br /> }<br /> }</p> </pre> </div> <p>以上流程基本上能满足大部分angular项目的国际化需求,如果需要更加复杂的国际化情况,欢迎讨论。</p> <h2>总结 </h2> <p>Angular到5.0的国际化已经相对来说简便了很多,我们只需要在合适的地方打上i18n的tag即可方便<a href="/tag/kuaisu/" target="_blank" class="keywords">快速</a>地<a href="/tag/tiqu/" target="_blank" class="keywords">提取</a>需要翻译文案,具体如何处理翻译后的<a href="/tag/wenjian/" target="_blank" class="keywords">文件</a>因人而异,多种<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>可帮助我们转换(如本文通过nodejs)。</p> <p>复杂一点的是无法通过打i18n<a href="/tag/biaoqian/" target="_blank" class="keywords">标签</a>来翻译的文本,NG-ZORRO的国际化方案弥补了这方面的不足,结合起来可以很方便地完成项目的国际化。 国际化如果没有专门的团队<a href="/tag/zhichi/" target="_blank" class="keywords">支持</a>,翻译难度很大,需要考虑的东西很多,比如繁体还有澳门繁体、台湾繁体等,语法也不尽相同。</p> <p><h3>参考目录 </h3></p> <p><a target="_blank" href="https://embed.plnkr.co/?show=preview" rel="external nofollow" >Angular的国际化(i18n)在线例子 </a> <a target="_blank" href="https://ng.ant.design/#/other/locale" rel="external nofollow" >NG-ZORRO Locale 国际化</a></p> <p>以上就是本文的全部<a href="/tag/neirong/" target="_blank" class="keywords">内容</a>,希望对大家的学习有所帮助,也希望大家多多<a href="/tag/zhichi/" target="_blank" class="keywords">支持</a>编程之家。</p></div> <div class="topcard-tags"><a href="/tag/guojihua/" class="tag_link" target="_blank">国际化</a><a href="/tag/guojihuap/" class="tag_link" target="_blank">国际化</a><a href="/tag/pguojihua/" class="tag_link" target="_blank">国际化</a><a href="/tag/xiangmuguojihua/" class="tag_link" target="_blank">项目国际化</a></div> <ul class="list-group"> <li class="list-group-item"><a href="/js/34276.html" title="关于react-router/react-router-dom v4 history不能访问问题的解决">上一篇:关于react-router/react-router-do</a><a href="/js/34263.html" title="react-router v4如何使用history控制路由跳转详解" class="text-muted pull-right">下一篇:react-router v4如何使用history控</a> </li> </ul> </div> </div> </div> <!-- row end --> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <ins class="adsbygoogle" style="display:block" data-ad-format="autorelaxed" data-ad-client="ca-pub-4605373693034661" data-ad-slot="9144498553"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script></div> </div> </div> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <div class="title"><h1>猜你在找的JavaScript相关文章</h1></div> <div class="list_con"> <a href="/js/997747.html" title="Javascript中的事件冒泡与捕获"><div class="title">Javascript中的事件冒泡与捕获</div> <div class="summary">事件冒泡和事件捕获 起因:今天在封装一个bind函数的时候,发现el.addEventListener函数支...</div> <time class="summary">作者:前端之家 时间:2021-02-22</time> </a> </div> <div class="list_con"> <a href="/js/997746.html" title="搞懂js中小数运算精度问题原因及解决办法"><img class="lazy" src="/images/np.jpg" data-original="/res/2021/02-22/19/e40e1eb184cb2a5d8c5f6c5e730d8e82.png" title="" width="160" height="90" style="float:right;margin-left:30px;display:none;" /><div class="title">搞懂js中小数运算精度问题原因及解决办法</div> <div class="summary">js小数运算会出现精度问题 js number类型 JS 数字类型只有number类型,number类型相当于其...</div> <time class="summary">作者:前端之家 时间:2021-02-22</time> </a> </div> <div class="list_con"> <a href="/js/997744.html" title="搞懂:前端跨域问题JS解决跨域问题VUE代理解决跨域问题原理"><div class="title">搞懂:前端跨域问题JS解决跨域问题VUE代理解决跨域问题原理</div> <div class="summary">什么是跨域 跨域 : 广义的跨域包含一下内容 : 1.资源跳转(链接跳转,重定向跳转,表单提...</div> <time class="summary">作者:前端之家 时间:2021-02-22</time> </a> </div> <div class="list_con"> <a href="/js/997743.html" title="前端对base64编码的理解,原生js实现字符base64编码"><div class="title">前端对base64编码的理解,原生js实现字符base64编码</div> <div class="summary">@ &quot;TOC&quot; 常见对base64的认知(不完全正确) 首先对base64常见的认知,也是...</div> <time class="summary">作者:前端之家 时间:2021-02-22</time> </a> </div> <div class="list_con"> <a href="/js/997742.html" title="搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式"><div class="title">搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式</div> <div class="summary">搞懂:MVVM模式和Vue中的MVVM模式 MVVM MVVM : 的缩写,说都能直接说出来 :模型, :视图...</div> <time class="summary">作者:前端之家 时间:2021-02-22</time> </a> </div> <div style="border-bottom: 1px solid #f4f4f4;margin-top:20px;"> <ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-fr-2o+fp-dx-wx" data-ad-client="ca-pub-4605373693034661" data-ad-slot="4561116489"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div><div class="list_con"> <a href="/js/997318.html" title="js判断浏览器是否支持webGL"><div class="title">js判断浏览器是否支持webGL</div> <div class="summary">起因是我之前开发的网页,用到了three.js制作了一个3d的旋转球体效果。 在各种浏览器上运行...</div> <time class="summary">作者:前端之家 时间:2021-02-14</time> </a> </div> <div class="list_con"> <a href="/js/997317.html" title="js判断undefined和null"><div class="title">js判断undefined和null</div> <div class="summary">js判断undefined js判断null js判断null和undefined</div> <time class="summary">作者:前端之家 时间:2021-02-14</time> </a> </div> <div class="list_con"> <a href="/js/997316.html" title="将文字自动转为banner打印形式的工具"><div class="title">将文字自动转为banner打印形式的工具</div> <div class="summary">http://patorjk.com/software/taag/</div> <time class="summary">作者:前端之家 时间:2021-02-14</time> </a> </div> <div class="list_con"> <a href="/js/997315.html" title="聊一聊 bootstrap 的轮播图插件"><div class="title">聊一聊 bootstrap 的轮播图插件</div> <div class="summary">今天做工作的时候,轻车熟路的做完,又用到了bootstrap的轮播图,觉得有必要安利一下这个插...</div> <time class="summary">作者:前端之家 时间:2021-02-14</time> </a> </div> <div class="list_con"> <a href="/js/997314.html" title="js实现图片无缝循环跑马灯"><div class="title">js实现图片无缝循环跑马灯</div> <div class="summary">html 代码 css js代码 function mylsRunHorseLight() { if (mylsTimer != null) { clearIn...</div> <time class="summary">作者:前端之家 时间:2021-02-14</time> </a> </div> <div style="border-bottom: 1px solid #f4f4f4;margin-top:20px;"> <ins class="adsbygoogle" style="display:block" data-ad-format="fluid" data-ad-layout-key="-fr-2o+fp-dx-wx" data-ad-client="ca-pub-4605373693034661" data-ad-slot="4561116489"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div></div> </div> </div> </div> <!-- left end--> <!-- right --> <div class="col-sm-12 col-md-12 col-lg-3"> <!-- row --> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <label class="main-content-label ">编程分类</label> <div class="cate mt-20"><a href="/html/" title="HTML">HTML</a><a href="/html5/" title="HTML5">HTML5</a><a href="/js/" title="JavaScript">JavaScript</a><a href="/css/" title="CSS">CSS</a><a href="/jquery/" title="jQuery">jQuery</a><a href="/bootstrap/" title="Bootstrap">Bootstrap</a><a href="/angularjs/" title="Angularjs">Angularjs</a><a href="/typescript/" title="TypeScript">TypeScript</a><a href="/vue/" title="Vue">Vue</a><a href="/dojo/" title="Dojo">Dojo</a><a href="/json/" title="Json">Json</a><a href="/electron/" title="Electron">Electron</a><a href="/nodejs/" title="Node.js">Node.js</a><a href="/extjs/" title="extjs">extjs</a><a href="/express/" title="Express ">Express </a><a href="/xml/" title="XML">XML</a><a href="/es6/" title="ES6">ES6</a><a href="/ajax/" title="Ajax">Ajax</a><a href="/flash/" title="Flash">Flash</a><a href="/unity/" title="Unity">Unity</a><a href="/react/" title="React">React</a><a href="/flex/" title="Flex">Flex</a><a href="/antdesign/" title="Ant Design">Ant Design</a><a href="/webfrontend/" title="Web前端">Web前端</a><a href="/weapp/" title="微信小程序">微信小程序</a><a href="/wxmp/" title="微信公众号">微信公众号</a><div class="clearfix"></div> </div> </div> </div> </div> <!-- row end --> <!-- row --> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <!-- f2er-rightads --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-4605373693034661" data-ad-slot="7756441254" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div> </div> </div> <!-- row end --> <!-- row --> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <label class="main-content-label ">最新文章</label> <ul class="n-list"><li><a href="/js/997747.html" title="Javascript中的事件冒泡与捕获" target="_blank">• Javascript中的事件冒泡与</a></li> <li><a href="/js/997746.html" title="搞懂js中小数运算精度问题原因及解决办法" target="_blank">• 搞懂js中小数运算精度问题</a></li> <li><a href="/js/997744.html" title="搞懂:前端跨域问题JS解决跨域问题VUE代理解决跨域问题原理" target="_blank">• 搞懂:前端跨域问题JS解决</a></li> <li><a href="/js/997743.html" title="前端对base64编码的理解,原生js实现字符base64编码" target="_blank">• 前端对base64编码的理解,</a></li> <li><a href="/js/997742.html" title="搞懂:MVVM模型以及VUE中的数据绑定数据劫持发布订阅模式" target="_blank">• 搞懂:MVVM模型以及VUE中的</a></li> <li><a href="/js/997493.html" title="js实现横向跑马灯效果" target="_blank">• js实现横向跑马灯效果</a></li> <li><a href="/js/997318.html" title="js判断浏览器是否支持webGL" target="_blank">• js判断浏览器是否支持webG</a></li> <li><a href="/js/997317.html" title="js判断undefined和null" target="_blank">• js判断undefined和null</a></li> <li><a href="/js/997316.html" title="将文字自动转为banner打印形式的工具" target="_blank">• 将文字自动转为banner打印</a></li> <li><a href="/js/997315.html" title="聊一聊 bootstrap 的轮播图插件" target="_blank">• 聊一聊 bootstrap 的轮播图</a></li> </ul> </div> </div> </div> <!-- row end --> <!-- row --> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <label class="main-content-label ">热门标签 <span class="pull-right tx-12"> <a href="/all" target="_blank">更多 ►</a></span> </label> <div class="topcard-tags"><a href="/tag/guanbiyangao/" title="关闭广告" target="_blank">关闭广告</a><a href="/tag/danduheaders/" title="单独headers" target="_blank">单独headers</a><a href="/tag/fengzhuangdaima/" title="封装代码" target="_blank">封装代码</a><a href="/tag/tishicuowu/" title="提示错误" target="_blank">提示错误</a><a href="/tag/zhengshuzhengze/" title="整数正则" target="_blank">整数正则</a><a href="/tag/fei0kaitou/" title="非0开头" target="_blank">非0开头</a><a href="/tag/tiaoye/" title="跳页" target="_blank">跳页</a><a href="/tag/chuyema/" title="出页码" target="_blank">出页码</a><a href="/tag/antdtable/" title="antd table" target="_blank">antd table</a><a href="/tag/tishiURLweizhuce/" title="提示URL未注册" target="_blank">提示URL未注册</a><a href="/tag/gongzhonghaozhifu/" title="公众号支付" target="_blank">公众号支付</a><a href="/tag/vuehashmoshi/" title="vue hash模式" target="_blank">vue hash模式</a><a href="/tag/iSlider/" title="iSlider" target="_blank">iSlider</a><a href="/tag/chepaijianpan/" title="车牌键盘" target="_blank">车牌键盘</a><a href="/tag/xunhuantupian/" title="循环图片" target="_blank">循环图片</a><a href="/tag/echartsshuangzhexian/" title="echarts 双折线" target="_blank">echarts 双折</a><a href="/tag/zuoyoubuju/" title="左右布局" target="_blank">左右布局</a><a href="/tag/DllPlugin/" title="DllPlugin" target="_blank">DllPlugin</a><a href="/tag/duixiangchuangjian/" title="对象创建" target="_blank">对象创建</a><a href="/tag/daziyouxi/" title="打字游戏" target="_blank">打字游戏</a><a href="/tag/quanxuan/" title="圈选" target="_blank">圈选</a><a href="/tag/lianglan/" title="两栏" target="_blank">两栏</a><a href="/tag/yunhanshu/" title="云函数" target="_blank">云函数</a><a href="/tag/mengban/" title="蒙版" target="_blank">蒙版</a><a href="/tag/ES2020/" title="ES2020" target="_blank">ES2020</a><a href="/tag/chuchuang/" title="橱窗" target="_blank">橱窗</a><a href="/tag/wufenggundonglunbo/" title="无缝滚动轮播" target="_blank">无缝滚动轮播</a><a href="/tag/sekuaipengzhuang/" title="色块碰撞" target="_blank">色块碰撞</a><a href="/tag/zujianxiaohui/" title="组件销毁" target="_blank">组件销毁</a><a href="/tag/wendangcaozuo/" title="文档操作" target="_blank">文档操作</a></div> </div> </div> </div> <!-- row end --> <!-- row --> <div class="row row-sm"> <div class="col-sm-12 col-md-12 col-lg-12"> <div class="card"> <!-- f2er-rightads --> <ins class="adsbygoogle" style="display:block" data-ad-client="ca-pub-4605373693034661" data-ad-slot="7756441254" data-ad-format="auto" data-full-width-responsive="true"></ins> <script> (adsbygoogle = window.adsbygoogle || []).push({}); </script> </div> </div> </div> <!-- row end --> </div> <!-- right end --> </div> </div> <footer id="footer"> <div class="container"> <div class="row hidden-xs"> <dl class="col-sm-6 site-link"> <dt>最近更新</dt><dd><a href="/win11/1005328.html" title="小米手机重装系统价格多少?专业维修服务详解" target="_blank">· 小米手机重装系统价格多少?专业维修服务详解</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005327.html" title="手把手教你重装电脑系统,让你的电脑焕然一新!" target="_blank">· 手把手教你重装电脑系统,让你的电脑焕然一新!</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005326.html" title="教你一步步重装XP系统,让你的电脑重获新生" target="_blank">· 教你一步步重装XP系统,让你的电脑重获新生</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005325.html" title="从备份到上网:一步步教你重装电脑系统" target="_blank">· 从备份到上网:一步步教你重装电脑系统</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005324.html" title="Sony笔记本电脑一键重装系统详细图文教程" target="_blank">· Sony笔记本电脑一键重装系统详细图文教程</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005323.html" title="Lenovo笔记本重装系统超详细教程,小白也能轻松上手" target="_blank">· Lenovo笔记本重装系统超详细教程,小白也能轻松...</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005322.html" title="联想笔记本一键重装Win10系统详细教程" target="_blank">· 联想笔记本一键重装Win10系统详细教程</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005321.html" title="电脑系统故障无需愁,专业维修店帮你重装旧貌换新颜" target="_blank">· 电脑系统故障无需愁,专业维修店帮你重装旧貌换新...</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005320.html" title="联想笔记本一键重装Win10系统图文教程,小白也能轻松搞定!" target="_blank">· 联想笔记本一键重装Win10系统图文教程,小白也能...</a><span class="text-muted pull-right">02-05</span></dd> <dd><a href="/win11/1005319.html" title="笔记本重装系统图文教程:从光盘启动一步到位" target="_blank">· 笔记本重装系统图文教程:从光盘启动一步到位</a><span class="text-muted pull-right">02-05</span></dd> </dl> <dl class="col-sm-4 site-link"> <dt>好站推荐</dt><dd> <a href="https://www.runoob.com" title="菜鸟教程(www.runoob.com)提供了编程的基础技术教程, 介绍了HTML、CSS、Javascript、Python,Java,Ruby,C,PHP , MySQL等各种编程语言的基础知识。 同时本站中也提供了大量的在线实例,通过实例,您可以更好的学习编程。" target="_blank">菜鸟教程</a></dd><dd> <a href="https://www.jb51.cc" title="编程之家(www.jb51.cc)是成立于2017年面向全球中文开发者的技术内容分享平台。提供编程导航、编程问答、编程博文、编程百科、编程教程、编程工具、编程实例等开发者最需要的编程技术内容与开发工具支持,与你一起学习编程,相信编程改变未来!" target="_blank">编程之家</a></dd><dd> <a href="" title="前端之家 f2er.com 前端开发人员所需学习知识手册。" target="_blank">前端之家</a></dd></dl> <dl class="col-sm-2 site-link"> <dt>商务合作</dt> <dd><a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=76874919&site=qq&menu=yes">联系我们</a></dd> </dl> </div> <div class="copyright"> Copyright © 2019 前端之家. 当前版本 V7.0.16<br> <span class="ml5">前端之家 版权所有 <a href="https://beian.miit.gov.cn/" target="_blank" rel="nofollow">闽ICP备13020303号-10</a></span> </div> </div> </footer> <script type="text/javascript" src="/js/base.js"></script> </body> </html>