(编辑:jimmy 日期: 2024/11/19 浏览:2)
一、CKEditor4安装
安装CKEditor"font-size: medium;">二、集成
1、加载CKEditor
CKEditor"htmlcode">
<head> ...<script src="/UploadFiles/2021-04-02/ckeditor.js">当上述文件加载后,就可以使用CKEditor"htmlcode">
<textarea name="editor1"><p>Initial value.</p></textarea>"htmlcode">
<script>CKEDITOR.replace( 'editor1' );</script>此脚本块必须被包含在<textarea>标记后的页面源代码的任意位置。
你也可以在<head>部分调用replace函数,但此时需要监听window.onload事件:
<script>window.onload = function() {CKEDITOR.replace( 'editor1' ); };</script>保存编辑器的数据
如上所述,编辑器的工作方式类似于<textarea>域。这意味着当提交包含编辑器实例的表单时,数据将很简单地提交,使用<textarea>元素名作为键来检查它。
例如,接着上面的例子,我们可以生成下面的PHP代码:<"htmlcode"><script>var editor_data = CKEDITOR.instances.editor1.getData(); </script>完整的样例
要插入一个CKEditor实例,可以使用下面的样例来生成一个页面,它包含一个用CKEditor替换过的表单。
<html> <head> <title>CKEditor Sample</title> <script src="/UploadFiles/2021-04-02/ckeditor.js">3、内联式编辑(Inline"htmlcode">
<div id="editable" contenteditable="true"> <h1>Inline Editing in Action!</h1> <p>The div element that holds this text is now editable. </div>也可以通过代码来启用编辑,通过调用CKEDITOR.inline:
<div id="editable" contenteditable="true"> <h1>Inline Editing in Action!</h1> <p>The div element that holds this text is now editable.</p> </div> <script> // Turn off automatic editor creation first. CKEDITOR.disableAutoInline = true; CKEDITOR.inline( 'editable' ); </script>当在上面的<div>内容中点击时,CKEditor的工具栏就是出现。
检索编辑器的数据
跟框架式编辑不同,当使用内联式编辑时,用CKEditor编辑的数据没有放在<textarea>中,而是直接存在于页面的DOM中。因此,应用程序就要完成检查数据和存储所需的操作。
要检查编辑器的数据,简单地调用编辑器实例的CKEDITOR.editor.getData方法。对于上面的例子,如下:<script> var data = CKEDITOR.instances.editable.getData(); // Your code to save "data", usually though Ajax. </script>注意为了检索编辑器实例,最初的<div>"font-size: medium;">三、配置
1、设置CKEditor"htmlcode">
CKEDITOR.replace( 'editor1', { toolbar : 'Basic', uiColor : '#9AB8F3' });注意通过一个字面对象定义(以“{”符号开始,以“}”符号结束)来传递配置选项。因此,每个选项的正确语法是("配置的名字"):("配置的值")。一定不要在冒号字符(:)处使用“等于”字符(=)。
使用config.js文件
也可以通过使用config.js文件来配置CKEditor的设置。此文件缺省情况几乎为空。要改变CKEditor的配置,将你想要修改的设置增加到config.js文件中。例如:
CKEDITOR.editorConfig = function( config ) { config.language = 'fr'; config.uiColor = '#AADC6E'; };为了应用配置设置,必须总是要定义CKEDITOR.editorConfig函数。config.js文件将在页面范围中被执行,故你还可以引用在页面(In-Page)或者甚至是其它JavaScript文件中定义的变量。
使用定制的配置文件
使用定制的配置文件是另一种推荐的设置CKEditor配置的方法。不使用缺省的config.js文件,你可以将此文件复制到站点的任何地方,并简单地引导编辑器加载它。此方法的优点是采用此方法可以避免改变原始的文件,从而使以后升级CKEditor更容易,只是简单地覆盖所有的文件。
假设你将config.js文件复制到你的站点根目录下一个叫custom的文件夹中。你还将此文件更名为ckeditor_config.js。此时,要使用定义在文件中的定制设置,只需在生成编辑器实例时,设置customConfig配置选项即可。例如:
CKEDITOR.replace( 'editor1', { customConfig : '/custom/ckeditor_config.js' });定制的配置文件必须看起来像缺省的config.js文件。
配置的加载顺序
不要求你仅使用一种上述配置选项。可以混用上述方法,并且可以正确地加载配置。下面的列表表示在生成编辑器实例时所使用的配置加载顺序:
生成一个编辑器的实例。此时,其所有配置项设置为缺少值。
如果在页面中(in-page)中有配置设置,该文件被加载,否则加载缺省的config.js文件。在定制配置文件中的所有设置覆盖当前实例的配置。
如果在第二步加载的设置中还定义了新的customConfig值,就加载另一个配置文件,且其设置覆盖实例的当前设置。对所有文件递归,直到没有再定义customConfig。
最终,在页面中(in-page)中定义的设置覆盖实例的当前设置(除了customConfig,它已在第一步中使用过了)。
避免加载外部的设置文件
也可能完全避免加载外部的配置文件,以减少加载的文件数。为此,你需要将
CKEDITOR.config.customConfig设置为空字符串。例如:CKEDITOR.replace( 'editor1', { customConfig : ' ' });如果你在config.js文件中没有配置,也没有定制的配置文件,则一定推荐此设置。
2、工具栏的定制
虽然CKEditor是一个功能齐全的“所见即所得”编辑器,但是并不是其所有选项在所有情况下都需要。因此,工具栏定制是最常用需求之一。
有两种方法配置工具栏来匹配需求:
工具栏组配置
“逐项”配置
工具栏组配置
CKEditor"htmlcode">
config.toolbarGroups = [ { name: 'clipboard', groups: [ 'clipboard', 'undo' ] }, { name: 'editing', groups: [ 'find', 'selection', 'spellchecker' ] }, { name: 'links' }, { name: 'insert' }, { name: 'forms' }, { name: 'tools' }, { name: 'document', groups: [ 'mode', 'document', 'doctools' ] }, { name: 'others' }, '/', { name: 'basicstyles', groups: [ 'basicstyles', 'cleanup' ] }, { name: 'paragraph', groups: [ 'list', 'indent', 'blocks', 'align' ] }, { name: 'styles' }, { name: 'colors' }, { name: 'about' } ];它是一个对象的列表(数组),每一项有一个“name”(如"clipboard"或"links")和一个可选的“子组”列表。
"htmlcode">
config.toolbar = [ { name: 'document', items: [ 'Source', '-', 'NewPage', 'Preview', '-', 'Templates' ] }, { name: 'clipboard', items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] }, '/', { name: 'basicstyles', items: [ 'Bold', 'Italic' ] } ];"htmlcode">
config.toolbar = [ [ 'Source', '-', 'NewPage', 'Preview', '-', 'Templates' ], [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ], '/', [ 'Bold', 'Italic' ] ];通过将'-'(短线)加到项目列表中,将项目分隔符包括其中,如上面看到的。
将'/'加到组之间,可以在工具栏中强制断行。它们可以用于在其放置的位置强制断行,使得下一个工具栏组处于新的一行。"htmlcode">
CKEDITOR.stylesSet.add( 'my_styles', [ // Block-level styles { name: 'Blue Title', element: 'h2', styles: { 'color': 'Blue' } }, { name: 'Red Title' , element: 'h3', styles: { 'color': 'Red' } }, // Inline styles { name: 'CSS Style', element: 'span', attributes: { 'class': 'my_style' } }, { name: 'Marker: Yellow', element: 'span', styles: { 'background-color': 'Yellow' } } ]);如上面所示的样式定义注册可以内置于页面源代码中,或者存在于外部文件中,只要需要时,“按需”加载。(见下面)。
当准备好定义后,你必须通过使用stylesSet设置使编辑器应用新注册的样式。这可以在config.js文件中设置,例如:
config.stylesSet = 'my_styles';使用外部样式定义文件
可以将样式定义的注册调用包含在一个外部JavaScript文件中。缺省情况,CKEditor从其安装文件夹中的styles.js文件中加载样式定义。
你的样式定义文件可以保存在站点的任意地方(或互联网的某个地方)。但,你必须知道访问它所需的URL。例如,你可以将此文件保存在站点的根目录中,然后按/styles.js调用它,或者放在其它任意地方,并使用其完整的URL引用它,如http://www.example.com/styles.js。此时,改变stylesSet设置,使编辑器指向此文件:
config.stylesSet = 'my_styles:/styles.js'; //或者 config.stylesSet = 'my_styles:http://www.example.com/styles.js';样式定义设置的语法总是:样式定义名称:文件的URL。
注意,必须使用在此文件中注册样式定义时使用过的唯一的名称。样式规则
在样式定义中的输入项称为“样式规则”。每条规则定义了单个样式的显示名字和元素、属性以及所使用的CSS样式。下面是它的一般表现形式:{ name: 'Name displayed in the Styles drop-down list', element: 'HTML element name (for example "span")', styles: { 'css-style1': 'desired value', 'css-style2': 'desired value', ... } attributes: { 'attribute-name1': 'desired value', 'attribute-name2': 'desired value', ... } }名称和元素值是必须的,而其它的值是可选的。
样式的类型
有三种样式类型,每一种都与在样式规则中使用的元素相关:
块级样式(Block-level"htmlcode">
config.contentsCss = 'sample_CSS_file.css';这种解决方法使得可以配置编辑器使用现有的CSS样式单规则,而不需要为CKEditor生成单独的样式定义。另一方面,前面使用的方法提供了对用户可以使用样式的更多控制,因此,两种方法可以按需要互换使用。
选择CSS选择器
可以细调此插件,以使只考虑与stylesheetParser_validSelectors配置值相匹配的CSS选择器。默认的正则表达式接受"htmlcode">
// Only add rules for <p> and <span> elements.(仅为<p>和<span>元素增加规则 config.stylesheetParser_validSelectors = /\^(p|span)\.\w+/;限制CSS选择器
通过设置stylesheetParser_skipSelectors的配置值,也可以进行定制。那么,该插件将会角力忽略与正则表达式相匹配的CSS规则,不会在下拉列表中显示它们,也不会使用它们输出文档内容。默认值不包括为<body>的所有元素和为非具体元素定义的类,但可以修改它,以忽略更广泛的元素集,如下例:
// Ignore rules for <body> and <caption> elements, classes starting with "high", and any class defined for no specific element.(忽略<body>和<caption>元素、以“high”开头的类,以及为非具体元素定义的类的规则) config.stylesheetParser_skipSelectors = /(^body\.|^caption\.|\.high|^\.)/i;"true"。所有可用的编辑器功能将被激活,并且将不会过滤输入的数据。
自动模式
当没有提供CKEDITOR.config.allowedContent设置时,高级内容过滤器工作于自动模式。在编辑器初始化时,编辑功能将其规则添加到过滤器。因此,只允许使用当前加载的功能可以编辑的内容,其余所有内容都被过滤掉。
下面的例子或许可以较容易地理解ACF的自动模式。1."font-weight:700|800|900|bold">" list-paddingleft-2">
" list-paddingleft-2">
如果一个元素不存在规则,则删除它。
可能接受一个元素,但拒绝其所有的属性,然后就被删除。
一旦被验证,一个元素和它的属性不能被另一规则使之失效。
字符串格式(String"htmlcode">
elements [attributes]{styles}(classes)正则表达式模板: "htmlcode">
<elements><styles, attributes, and classes><separator> /^([a-z0-9*\s]+)((" list-paddingleft-2">elements" list-paddingleft-2">
用于元素列表中的星号意思是:“该规则对所有元素接受后面的属性,但不是这些元素本身;必须有另一条规则显式地接受这些元素”。
属性列表中的星号意思是:“接受所有属性”。
用于属性列表中条目名前的感叹号(!)(如:[!href])意思是:“此属性是必需的。
如果一个元素不具有此属性,此规则不应应用于该元素(故此元素将不会由它得到验证)”。
例子:
// 一条规则接受<p>和<h1>元素,但没有任何属性。 p h1 //一条规则接受具有可选的"left"和 "right"类的<p>和<h1>元素 //注意:两个元素都可能含有这些类,而不仅仅是<h1> p h1(left,right) //一条规则接受具有其所有属性的<p>和<h1>元素 p h1[*] //一条规则接受<a>,只有当它含有"href"属性时。 a[!href] //一条规则接受<img>,它具有必需的"src"属性和一个可选的"alt"属性,加上可选的"width"和"height"样式 img[alt,!src]{width,height} //与上面相同,因为属性的顺序和其清单是不相关的,并且忽略空格 img { height, width } [ !src, alt ]允许内容规则集可以含有由分号(;)分隔的多条规则。如:
// 这些规则允许: // 具有可选的"text-align"样式的<p和><h1>元素 //具有必需的"href"属性的<a> // <strong> 和 <em> 元素, //具有可选的"tip"类的<p>(故<p>元素可以同时具有"text-align"样式和"tip"类) p h1{text-align}; a[!href]; strong em; p(tip) //这些规则允许: // 具有可选的"id"属性的<p>和<h1>元素 //具有必需的"href"属性和可选的"id"属性的<a> p h1; a[!href]; *[id]调试
为了验证允许内容规则是否被正确解析了,可以检查CKEDITOR.editor.filter对象的CKEDITOR.filter.allowedContent属性。
var editor = CKEDITOR.replace( 'textarea_id', { allowedContent: 'a[!href]; ul; li{text-align}(someclass)' } ); editor.on( 'instanceReady', function() { console.log( editor.filter.allowedContent ) "htmlcode">allowedContent: 'p h1{text-align}; a[!href]; strong em; p(tip)' //与下面的相对应: allowedContent: { 'p h1': { styles: 'text-align' }, a: { attributes: '!href' }, 'strong em': true, p: { classes: 'tip' } }采用此方法,允许内容规则可以由JavaScript动态地生成,并因任意目的存储成JSON数据格式。注意:对象字面量的键必须是唯一的,因此:
allowedContent: { p: { styles: 'text-align' }, p: { classes: 'tip' } } //等价于: allowedContent: 'p(tip)' //但永远不会是: allowedContent: 'p{text-align}(tip)'"writer"来编写输出数据。因此,可以用editor.dataProcessor.writer属性检索出具体编辑器实例的当前编写器。
通过设置writer属性可以配置几种输出格式化选项。下面的例子概括了最常用的几种,给出了其默认值:
var writer = editor.dataProcessor.writer; // 生一缩进步使用的字符串 writer.indentationChars = '\t'; //自结束标记的方式,就像<br /> writer.selfClosingEnd = ' />'; // 断行所使用的字符串 writer.lineBreakChars = '\n'; // 标记的编写规则 writer.setRules( 'p', { // 表示在此标记中断行时缩进 indent: true, //在<p>的开始标记前插入断行符 breakBeforeOpen: true, //在<p>的开始标记后插入断行符 breakAfterOpen: true, // 在<p>的结束标记前插入断行符 breakBeforeClose: false, // 在<p>的结束标记后插入断行符 breakAfterClose: true });设置编写器规则
因为编辑器是每个编辑器实例的属性,并且由于对加载的编写器插件的依赖,对它进行修改的最好方法是监听CKEDITOR.instanceReady事件;这样含义可以安全地假设CKEDITOR.editor.dataProcessor属性将会被加载,并准备好可以修改。下面的代码展示了当生成编辑器实例时使用此方法的例子:
CKEDITOR.replace( 'editor1', { on: { instanceReady: function( ev ) { // Output paragraphs as <p>Text</p>. this.dataProcessor.writer.setRules( 'p', { indent: false, breakBeforeOpen: true, breakAfterOpen: false, breakBeforeClose: false, breakAfterClose: true }); } } });另一种方法是使用CKEDITOR对象,这样所有的编辑器实例会被改变:
CKEDITOR.on( 'instanceReady', function( ev ) { // Ends self closing tags the HTML4 way, like <br>. ev.editor.dataProcessor.writer.selfClosingEnd = '>'; });"htmlcode">
config.disableNativeSpellChecker = false;在重新加载编辑器后,应该可以看到内容下面的拼写下划线。
注意:如果上下文菜单插件生效,需要在右击时按信CTRL键来查看建议。"font-size: medium;">7、文件浏览器和上传与文件浏览器集成
CKEditor可以容易地与外部文件浏览器/上传器进行集成。
一旦正确地配置了,所有的文件浏览器功能将会自动变成可用基本配置" list-paddingleft-2">
filebrowserBrowseUrl设置含有外部浏览器的位置,当按了Browse"htmlcode">
CKEDITOR.replace( 'editor1', { filebrowserBrowseUrl: '/browser/browse.php', filebrowserUploadUrl: '/uploader/upload.php' });例2
也可以通过在文件浏览器设置:filebrowserBrowseUrl和filebrowserUploadUrl中,使用对话窗口名来为所选的对话窗口设置单独的URL。
对于为图像对话窗口设置特殊的上传URL的例子,使用"htmlcode">CKEDITOR.replace( 'editor1', { filebrowserBrowseUrl: '/browser/browse.php', filebrowserImageBrowseUrl: '/browser/browse.php"800")。如果你喜欢将窗口的高度和宽度设置为屏幕的百分数,不要忘记在数字后面加上百分号(如"60%")。例3
下面例子给出的基本配置代码可以用于插入到配置了文件浏览器路径和窗口大小的CKEditor中。
CKEDITOR.replace( 'editor1', { filebrowserBrowseUrl: '/browser/browse.php', filebrowserUploadUrl: '/uploader/upload.php', filebrowserWindowWidth: '640', filebrowserWindowHeight: '480' });要为指定的对话窗口设置文件浏览器的窗口大小,使用filebrowserWindowWidth和filebrowserWindowHeight"Image"对话框中的文件浏览器的窗口大小,改变filebrowserImageWindowWidth和filebrowserImageWindowHeight的设置。
例4
下面例子给出的基本配置代码可以用于插入到配置了文件浏览器路径的CKEditor中。它还改变了文件浏览器窗口的默认尺寸,但仅当从Image"htmlcode">
CKEDITOR.replace( 'editor1', { filebrowserBrowseUrl: '/browser/browse.php', filebrowserUploadUrl: '/uploader/upload.php', filebrowserImageWindowWidth: '640', filebrowserImageWindowHeight: '480' });使用CKFinder
CKEditor可以很容易地与CKFinder集成,它是一个高级的Ajax文件浏览器。看这里的现场演示。
可以用两种方式实现集成:通过设置CKEditor配置选项(下面的例子)或通过使用CKFinder"htmlcode">CKEDITOR.replace( 'editor1', { filebrowserBrowseUrl: '/ckfinder/ckfinder.html', filebrowserImageBrowseUrl: '/ckfinder/ckfinder.html" list-paddingleft-2">asp"htmlcode">
var editor = CKEDITOR.replace( 'editor1' ); CKFinder.SetupCKEditor( editor, '/ckfinder/' );SetupCKEditor()方法的第二个参数是CKFinder的安装路径。
请查看与CKFinder一起发布的"font-size: medium;"> CKEditor4 PHP" list-paddingleft-2">Creating" list-paddingleft-2">
CKEditor"htmlcode">
CKEDITOR.replace( 'editor2', { filebrowserBrowseUrl: '/browser/browse.php" list-paddingleft-2">/browser/browse.php"htmlcode">
window.opener.CKEDITOR.tools.callFunction( funcNum, fileUrl [, data] );如果data(第三个参数)是字符串,将由CKEditor进行显示。如果在文件上传时发生了问题,此参数通常作为错误信息显示。
例2
下面的例子说明了如何使用JavaScript代码从文件浏览器中传递URL:
//从查询字符串中获得参数的"htmlcode">
function getUrlParam( paramName ) { var reParam = new RegExp( '("htmlcode"><"<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($funcNum, '$url', '$message');</script>"; "htmlcode">window.opener.CKEDITOR.tools.callFunction( funcNum, fileUrl, function() { // 获得对话窗口的引用 var element, dialog = this.getDialog(); //检查是否为Image对话窗口 if ( dialog.getName() == 'image' ) { // 获得具有"alt"属性的文本域的引用 element = dialog.getContentElement( 'info', 'txtAlt' ); // 赋新值 if ( element ) element.setValue( 'alt text' ); } ... // 返回false,停止进一步执行- - 在这种情况下,CKEditor将忽略第二个参数 (fileUrl) // 和赋给调用文件浏览器按钮的onSelect函数 (如果定义了). [return false;] });将文件浏览器添加到对话框中
CKEditor可以很容易地与你自己的文件浏览器集成。
要连接与CKEditor兼容的文件浏览器(如"Browse"按钮
要将文件浏览器插件添加到一个对话框中的元素,设置"filebrowser"属性。在image插件的例子中,有:
{ type: 'button', hidden: true, id: 'browse', filebrowser: ' Link:txtUrl', label: editor.lang.common.browseServer, style: 'float:right', },此按钮默认是隐藏的"Quick"支持
再次看看如何在我们的对话框中处理文件上传,我们将使用来自CKEditor的工作示例。在image插件中,有一个Upload标签定义:
{ id: 'Upload', hidden: true, filebrowser: 'uploadButton', label: editor.lang.image.upload, elements: [ { type: 'file', id: 'upload', label: editor.lang.image.btnUpload, style: 'height:40px', size: 38 }, { type: 'fileButton', id: 'uploadButton', filebrowser: 'info:txtUrl', label: editor.lang.image.btnUpload, 'for': [ 'Upload', 'upload' ] } ] },此例较前一例子稍复杂一些因为
1)这里有整个标签的定义
2)我们需要两个元素:file和fileButton来上传文件。
在上面的例子中,标签的id为'Upload'。它默认是隐藏的(hidden:true)。正如已提到的,文件浏览器插件查找具有filebrowser属性的所有元素,并且如果相应的配置设置可用就不隐藏它们。
在此例中,如果'uploadButton'文件浏览器设置(因为filebrowser:'uploadButton')将成为可用(filebrowserUploadUrl),则将自动不再隐藏此标签。
file元素很简单,不需要做解释,它只是一个input元素,将保存将要上传的文件名。"htmlcode">
{ type: 'button', hidden: true, id: 'id0', label: editor.lang.common.browseServer, filebrowser: { action: 'Browse', // target: 'tab1:id1', onSelect: function( fileUrl, data ) { alert( 'The selected file URL is "' + fileUrl + '"' ); for ( var _info in data ) alert( 'data[ "' + _info + '" ]' + ' = ' + data[ _info ] ); var dialog = this.getDialog(); dialog.getContentElement( 'tab1', 'id1' ).setValue( data[ 'fileUrl' ] ); //不要调用内置的onSelect命令 return false; } } }在此例中,我们设置了'Browse'操作,当点击按钮时调用文件浏览器。'target'不是必需的,因为我们将在定制的onSelect函数中更新目标元素。
如在此文档中说明的,当用户选择了一个文件时,我们已调用了"htmlcode">
{ type: 'file', label: editor.lang.common.upload, labelLayout: 'vertical', id: 'id2' }, { type: 'fileButton', label: editor.lang.common.uploadSubmit, id: 'id3', filebrowser: { action: 'QuickUpload', params: { type: 'Files', currentFolder: '/folder/' }, target: 'tab1:id1', onSelect: function( fileUrl, errorMessage ) { alert( 'The url of uploaded file is: ' + fileUrl + '\nerrorMessage: ' + errorMessage ); // Do not call the built-in onSelect command // return false; } }, 'for': [ 'tab1', 'id2' ] }在filebrowser.params属性中,我们可以添加其它参数,在查询字符串中传递给外部文件浏览器。filebrowser.target是当通过服务器连接器(uploader)返回文件时被更新的目标元素--如果我们定义了自己的onSelect函数(filebrowser.onSelect)并在此函数中更新了目标元素,就像前一例子中的作法,我们就不不需要此目标元素。
四、CKEditor4定制
1、CKEditor4插件
CKEditor是完全基于插件的。实际上,编辑器的核心是一个空盒子,它由插件提供的功能来进行填充。甚至编辑器的界面,像工具栏、按钮和编辑区也是插件。
CKEditor的默认安装,可能你正在使用,具有一些展现于其中的插件。你可以将插件添加到你的编辑器中,给你的用户带来更好更有用的功能。
在哪里寻找插件?
CKEditor"Add""技术"名字相匹配的子文件夹中。例如,"技术"名字相匹配的子文件夹中。例如,Kama skin 将被安装到这样的文件夹中:<CKEditor folder>/skins/kama。
3. Enabling the plugin: Now you must just setup CKEditor, by using the skin configuration
option:4. 使插件生效:现在你只需要配置CKEditor,通过使用skin配置选项: config.skin = 'kama';
就是这些。现在新皮肤就可以在CKEditor中生效了。
CKEditor4说明文档非常庞大,这里仅为大家分享了一些CKEditor4常用的配置与开发中文说明文档,如需要更详细的大家可以到CKEditor4官方网站上去查询
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?