首頁 web前端 css教學 從css談模組化

從css談模組化

Mar 29, 2017 pm 03:40 PM
css 模組化

模組化是現今我們隨處都可以聽到的名詞,什麼是模組化?為什麼我們需要模組化?這是本系列文章我們要弄清楚的問題。我們也藉這部分內容,順帶回顧一下前端的發展歷程。

 

說實話,模組化這個主題有點大,我一時也不知道從哪裡講起比較合適,通常來說,前端的工作內容主要涉及三個方面:html、css、js(javascript),其他的像as( actionscript,flash的腳本語言)、jsp、smarty等等模版類別的語法標記我們在此就先略去了,因為不是特別重要。那我們所說的模組化也可以分別當成這三條線去看,如html的模組化、css的模組化,以及js的模組化,這三者我們稱為(web)前端模組化,搞清楚這幾者的關係,我們接下來要了解的事情已經很清楚了。

我們單獨來講,我想先從css,因為這是我認為最容易入手且非常鮮明的一塊內容。

背景

起初的.css是長什麼樣子的?

/* index.css */

body {
  margin: 0;
  padding: 0;
  font-size: 18px;
}

.box {
  background: #333;
  color: #fff;
}

.box .list {
  margin-left: 10px;
}

.box .list .item {
  border-bottom: 1px solid #ccc;
}

.box .list .item:last-child {
  border-bottom: 0;
}

.box .list .item a {
  text-decoration: none;
  color: #fff;
}

.box .list .item span {
  color: red;
}

.box .list .item a ... {
  ...
}
登入後複製

是不是很熟悉?一個簡單的手打的列表模組。

這裡存在的問題是:

  • 依照這個順序寫下去,選擇器會越寫越長,造成書寫累贅;




  • ## 越來越長的選擇者容易使我們混淆dom的空間順序,想像如果有好幾個平級的選擇器(如.box .list .item a與.box .list .item span),我們可能一時看不出這兩者的關係,是父子還是兄弟元素?

  • # 維護困難,假設我們需要重構這個box,在.box和.list之間加入一層.wrap,在.item與a和span之間加入一層.block,那簡直就是個災難,我們要謹慎地找到確切的位置,然後再找到所有相符的、長長的選擇器,在適當的位置全部做修改;


  • 我們很難從做到復用,假設我們在另一個頁面也需要這個box,那我們就需要把所有跟box相關的部分複製貼上一份,而當這個box需要修改的時候,我們可能要重新找出所有用到這個box的地方,然後又是複製貼上一份——當然,有人說這個問題是可以用一定的方法解決的,我們後面再來討論這個問題;

  • ……


    (歡迎補充css的開發痛點)

  • # 事實上我們手打css遇到的問題可以大致歸納為以下幾點:
  • # 選擇器繁瑣冗長;

  • 命名衝突;

# 層級結構不清晰;

  1. # 程式碼難以重複使用;

  2. 問題很多,怎麼去解決?由於css的發展很緩慢,在工具上也一直沒有進展,導致這些問題,例如上述的第一點,幾乎無解。所以問題往往要依賴「規範」來解決。我們先來看程式碼復用。

    復用
  3. 要實作程式碼重複使用很簡單,我們只需要提供一個公共css函式庫,來存放我們的公共樣式以及公共模組:

    /* common.css */
    
    body {
      background: #fff;
      color: #333;
      font-size: 16px;
    }
    
    .box ... {
      background: #333;
      color: #fff;
      ...
    }
    
    .another-box ... {
      ...
    }
    登入後複製

    然後我們在其他的css檔案中引用這個common.css,這樣就實現了程式碼的複用,只要是想全域共享的樣式和模組,只要在這裡加入進去就可以了。
  4. <!-- index.html -->
    
    <!DOCTYPE html>
    <html>
    <head>
      <title>index</title>
      <link rel="stylesheet" type="text/css" href="./style/common.css">
      <link rel="stylesheet" type="text/css" href="./style/index.css">
    </head>
    <body>
      <p class="box">
        ...
      </p>
      <p class="another-box">
        ...
      </p>
    </body>
    </html>
    登入後複製
  5. 很完美,


    ——至少目前為止是這樣沒錯。

  6. 這裡我們來探究幾種情況:
  7. 假設我們這個專案非常大,大概有20個頁面這麼多,那麼我們每做一個頁面就會往common裡面補充3~4個公共樣式/模組,那麼在這個專案開發完成以後,common的體積可能會比其他css的體積都大;

  8. ################ 假設有幾個這樣的頁面,他們本身內容非常少,例如404頁面,可能只需要用到少量的公共樣式,但是由於考慮到維護問題,我們還是要引入common(單獨寫樣式會使得該頁面在common更新的時候無法同步得到更新),這就使得一個頁面變得很「重」;########################### 由於common越寫越大,它所佔用的命名就越多,那麼我們在引入common的時候,即使我們頁面還什麼都沒有,但已經默認被佔用了很多的命名,使得我們在某個頁面的可用命名變少,而且是越來越少;##################
  9. 我们在common中书写公共模块,在具体页面的私有css里书写私有模块,假设现在我们需要全局添加一个公共模块.nice-box,我们发现,这个模块名已经在index.css中被占用了,于是我们试着把名字改成.handsome-box,却又发现这个名字在about.css中被占用了,哦买噶的!

……

瞬间整个人都不好了,内心充满了绝望,心想还是转行吧,垃圾语言毁我一生。

我们分析一下,上面这些情况其实重点只有两个:一、冗余;二、污染。冗余是难免的,为了维护牺牲一部分灵活性也是可以接受的,不过我们需要用一些方式来减少这样的冗余,避免让它成为负担;而污染,却是亟待解决的问题,这颗定时炸弹随着项目的增大最终会变成一场无法挽回的灾难!这时候就体现出了命名规范的重要性了。

这就要求我们用一套合理的规范来约束和组织我们的代码。

规范

编程规范使得我们的项目在一定程度上是可维护的。比如针对类名污染制定了命名规范,针对选择器指定了书写选择器所要遵循的规范,等等。这些规范都在一定程度上约束了css的书写,使得项目不至于混乱。网易的NEC是其中一种比较完整的解决方案。有兴趣的童鞋可以搜索了解,笔者本身受nec影响较大,所以以下内容有一定程度的雷同。

现在我们来试着制定一套css编程规范,来解决以上提到的问题。

我们规定页面由且只由几种基本结构体构成:框架、模块,以及元件。其他零散的元素,除了是作为模块的辅助类,否则不能独立于这三者存在。

框架

框架是指构成页面的基础结构,它是一个页面的筋骨。我们假设有个页面index.html,它的整体最外围表现为一个class为.g-index的p,然后它由页头(.g-hd)、主体(.g-bd)、页脚(.g-ft)三个部分组成:

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-hd"></p>
    <p class="g-bd"></p>
    <p class="g-ft"></p>
  </p>
</body>
</html>
登入後複製

这样我们就大概能描绘出一个页面的基本轮廓了。紧接着我们来给它补充一些模块。

模块

模块是页面上数量最多,同时也是最重要的部分,它是代码复用的主体部分,是一个个按照功能划分的区域,如导航栏、轮播图、登录窗口、信息列表等等,模块之间相互独立,分布在页面上,嵌在框架的各个位置上,组成一个丰富多彩的页面。

还是以index.html为例,我们假设页头有个导航栏模块(.m-nav),主体有个新闻列表模块(.m-news),页脚有个版权声明模块(.m-copy_right):

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-hd">
      <p class="m-nav">
        nav
      </p>
    </p>
    <p class="g-bd">
      <p class="m-news">
        news
      </p>
    </p>
    <p class="g-ft">
      <p class="m-copy_right">
        copy_right
      </p>
    </p>
  </p>
</body>
</html>
登入後複製

元件

元件是独立的、可重复使用的,并且在某些情况下可以作为模块的组成部分的一种细颗粒。比如一个按钮,一个logo等等。某种意义上说,它其实可以等同于模块,因为它们两者的区别只是规模不同而已。模块更强调一个功能完整的整体,而元件则更强调独立性。

我们假设这个页面还需要在页头放个logo(.u-logo),在导航栏中放置一个登录按钮(.u-login_btn):

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-hd">
      <img class="u-logo" alt="logo">
      <p class="m-nav">
        nav
        <a href="/logoin" class="u-login_btn">登录</a>
      </p>
    </p>
    <p class="g-bd">
      <p class="m-news">
        news
      </p>
    </p>
    <p class="g-ft">
      <p class="m-copy_right">
        copy_right
      </p>
    </p>
  </p>
</body>
</html>
登入後複製

三种基本结构体介绍完,我们回来总结一下。你一定发现了一个现象,在搭建框架的时候,我给框架元素命名用g-开头,给模块命名使用m-,给元件命名使用u-。这是命名规范的一部分,我们使用这三个前缀给相应结构体命名,就是为了更好地标志一个结构体,更好地展示它的功用,这也是我们常说的 语义化 ,同时也能实现隔离作用,起到类似命名空间的效果。

  1. 框架的命名以g-开头,一般与页面同名,比如index.html,那框架就是最外层就是.g-index,about.html就是.g-about,以此类推,其他常用的内部结构有.g-hd(header)、.g-bd(body)、.g-ft(footer)、.g-sd(side)、.g-mn(main)等等;


  2. 模块命名以m-开头,一般以相对应的用途来命名,比如导航栏m-nav、新闻m-news、版权m-copy_right等等,一般来说模块名是唯一的,而且模块本身应该是可移植、可复用的;


  3. 元件命名以u-开头,一般以自身含义来命名,比如u-logo表示一个logo,u-btn表示一个按钮。

那么除却框架、模块、元件的相关命名内容之外,命名规范还有以下几点内容:

  1. 命名尽量以缩写的方式,言简意赅地表达,比如用bd表达body,用nav表达navigator等,使用长长的单词显得多余又臃肿;


  2. 前缀与名称之间用-连接,而名称之间的若干单词以_连接,组合单词除外,如side-menu;


  3. z-开头表示状态,如z-active、z-succ、z-disabled等等;


  4. 可以根据需要定制其他开头,但是请尽量将分类控制在少数,因为太多的分类反而造成困惑和不必要的分类开销,其实gmuz就已经可以满足日常开发了。

重构common

有了命名规范,我们可以对common进行一次改写:

/* common.css */

body {
  background: #fff;
  color: #333;
  font-size: 16px;
}

.m-nav { ... }

.m-news { ... }

.m-copy_right { ... }
登入後複製

ok,现在我们一定程度上缓解了“污染”的问题,至少按照命名规范,我们的common构成由原来笼统的一类,变成了现在gmuz四类,变得更加可管理且“没那么容易冲突”了,但是这还远没有解决“污染”。

以下为了方便表述,我们把common.css称为“common”,把对应页面的css,比如index.html -> index.css、about.html -> about.css,称为“页面css”。

这里有个问题需要细致思考一下:模块的属性。理论上讲,一个模块应该是公有或者私有的,假设一个模块它基本只可能在某个页面用,或者我们不打算在其他页面用到它,我们可以说这个模块是这个页面的私有模块,比如文章页里的文章列表模块(m-article_list),以及组成这个模块的列表单元元件(u-article_item),我们基本可以确定这两者不会在其他页面被复用到了,那么它们其实是已经默认私有的属性,没必要放在common里,直接放在article.css就可以了。这样也可以人为地减少common的体积。那么问题来了,如果模块既可以存放在common,又可以存放在页面css,那么我们后续在common中添加公共模块的时候,如何避免模块名已经在页面css中被占用的情况?(即上文对common的设计提问的第4点)

我曾经跟一位同事针对“后续添加公共模块可能与其他页面的私有模块命名冲突”的问题进行探讨,最后我们得出两种解决方案:

  1. 默认由common管理所有模块,所有模块默认为公共模块,不允许私有模块;


  2. 为公共模块单独使用一种前缀cm-来做区分,所有m-前缀的模块都是私有模块。

第一种方案会使得common体积非常大,而且会一直增大,不可取;第二种方案显式地声明模块属性,以此来避免冲突,可取。

于是乎又变成了:

/* common.css */

body {
  background: #fff;
  color: #333;
  font-size: 16px;
}

.cm-nav { ... }

.cm-news { ... }

.cm-copy_right { ... }
登入後複製

而我们的私有模块是这样的:

/* index.css */

.g-index {
  background: #fff;
  color: #333;
  font-size: 16px;
}

.m-nav { ... }

.m-news { ... }

.m-copy_right { ... }
登入後複製

这样子处理之后,我们的公共模块和私有模块之间的命名冲突就解决了,而且也不会出现“一个还什么都没有页面引用了common之后,许多的类名就被占用了”的情况,因为common绝大部分内容都是cm模块,而页面自己的css里只能拥有私有的m模块。

显然这种方案是可行的,但是我们会多一种前缀,而且还略丑。但就当时的手打css技术来说,我们没有其他更好的解决方案,这个问题就到这里暂算了结。我们解决了问题,但是方法还不够好,后续等我们提及css预处理语言的时候,我们会提出一些更好的解决方案。

好,接下来我们思考这样一个问题:假设我们已经写完了index页面,接着写about页面,这时候我们发现,原本在index中的一个模块m-news,我们将它归为私有模块,而现在在about中居然也需要用到这一个模块,于是乎,我们重新回到index页面,把m-news模块从index.css转移到了common.css当中,并改名为cm-news,然后回到index页面,把与m-news相关的内容(html、js)都修改成cm-news。这还是在我们能够意识到的情况下做的,如果页面多了起来,我们根本没有印象哪个页面是不是也有这样一个模块,要不要把它提升为公共模块。一个月之后,这个项目一个星期前已经搞定了,现在需要进行后续的开发,加多一个contact页面,然后我们又发现,这页面里用到了一个原本我们在about页面里把它划为私有模块的m-loc,于是乎,我们又走了一遍提升公共模块的流程。。。

为什么会出现这样的问题?根本原因在于,我们无法事先规划好所有的模块,无法在一开始就对一个模块的属性清晰地划分。这个问题也基本算是无解。矛盾在于,我们对模块进行了私有和公有的属性划分,却无法事先掌握所有的模块属性,只能走一步算一步,错了就回来再改改。

解决这问题的办法是,取消对模块的属性划分,所有模块都默认为公共模块,可以随时取用。但是这样就倒退回了我们之前的那种情况,所有的模块都是m-*,且都扎堆在common里,导致common的体积过大,所以这个问题只能到这里为止了。

模块

如何界定一个模块?或者说,怎么样才能把一部分代码划分为一个模块?划分的依据是什么?这是我们接下去要探讨的问题。

设计原则

我们说模块是一个功能相对独立且完整的结构体,其实这应该是 组件 的概念,我们这里只从css的范围内来探讨模块化,那么模块的定义就可以缩窄到:一个(组)样式相对独立且完整的类。比如:

/* copy_right */
.m-copy_right {
  color: #ccc;
  background: #666;
  font-size: 14px;
  text-align: center;
  padding: 20px 0;
  line-height: 1.8;
}

/* nav */
.m-nav {
  color: #ccc;
  background: #666;
  font-size: 14px;
}

.m-nav .u-logo { ... }

.m-nav .list { ... }

.m-nav .list .item { ... }
登入後複製

原则上来讲,一个css模块应该遵循以下几点要求:

只对外暴露一个类名;

/**
 * 正确示范,所有模块相关的代码都挂在模块的选择器名下
 */
.m-nav { ... }
.m-nav .list { ... }
.m-nav .list .item { ... }

/**
 * 错误示范,暴露了.m-nav和.list两个类名,污染了空间
 */
.m-nav { ... }
.list { ... }
.list .item { ... }
登入後複製

不影响周围布局:一般情况下,尽量不要使用一个脱离文档流的布局(既使用了float:left/right,position:absolute/fixed的布局),尽量不要使用外边距(margin)。这是为了使得模块更加稳定、具备更高的可塑性;

/**
 * 正确示范,在common中定义一个模块,在页面css中对模块进行定位和偏移
 */

/* common */
.u-logo {
  width: 100px;
  height: 100px;
}

.cm-news {
  width: 200px;
  height: 100px;
}

/* index */
.u-logo {
  position: absolute;
  left: 20px;
  top: 20px;
}

.cm-news {
  margin-top: 50px;
}
登入後複製
/**
 * 错误示范,在common中定义一个模块并固定它的位置
 */

/* common */
.u-logo {
  width: 100px;
  height: 100px;
  position: absolute;
  left: 20px;
  top: 20px;
}

.cm-news {
  width: 200px;
  height: 100px;
  margin-top: 50px;
}
登入後複製

模块尽量设计为方便复用的量级,避免大而全,求精巧;

<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-bd">
      <!-- 正确的示范 -->
      <!-- 创建一个大的内容块article_box,而不是一个大模块 -->
      <p class="article_box">
        <p class="hd">
          最新文章
        </p>
        <p class="bd">
          <p class="list">
            <!-- 这里我们把每一个项作为可复用的私有模块 -->
            <p class="m-list_item">
              <img class="cover" />
              <p class="info">
                <p class="title">
                  <a href="#">文章标题</a>
                </p>
                <p class="desc">文章简介</p>
              </p>
            </p>
          </p>
        </p>
        <p class="ft">
          <!-- 这里我们直接引入了一个公共分页模块 -->
          <p class="cm-page">
            <a href="#" class="pg">1</a>
            <a href="#" class="pg">2</a>
            <a href="#" class="pg">3</a>
            <a href="#" class="pg">4</a>
          </p>
        </p>
      </p>
    </p>
  </p>
</body>
</html>
登入後複製
<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-bd">
      <!-- 错误的示范 -->
      <!-- 创建一个庞大且不可复用的私有模块m-article_box -->
      <p class="m-article_box">
        <p class="hd">
          最新文章
        </p>
        <p class="bd">
          <p class="list">
            <p class="item">
              <img class="cover" />
              <p class="info">
                <p class="title">
                  <a href="#">文章标题</a>
                </p>
                <p class="desc">文章简介</p>
              </p>
            </p>
          </p>
        </p>
        <p class="ft">
          <p class="page">
            <a href="#" class="pg">1</a>
            <a href="#" class="pg">2</a>
            <a href="#" class="pg">3</a>
            <a href="#" class="pg">4</a>
          </p>
        </p>
      </p>
    </p>
  </p>
</body>
</html>
登入後複製

值得注意的是,这里的原则第三点,并不只是出于css模块化的考虑,事实上这更适用于 组件化 的设计思路,这在后面讲组件化的时候我们会提到。

继承

css的继承也是很简单的,一般来说是有这么几种方式:

  1. 在css中并写两个类,如.cm-nav, .m-nav,我们知道,这相当于让两个(组)类共享一套样式,然后我们再单独对.m-nav进行补充,实现继承和定制;


  2. 在class属性里并写两个类,如,这样我们只需要在页面css中单独对.logo类进行补充,就可以实现定制;


  3. 在页面css中直接对类进行引用
    ,然后补充样式,实现定制,如.cm-nav { margin-bottom: 20px; };

……

(还有许多黑魔法,欢迎补充)

第一种在我们这套模式里是不可取的,因为我们的公共模块都是放在common里,不可能每继承一次就上去补一个类;
第二种可取,但是需要多一个近似的类名,不提倡;
第三种又简单又靠谱。

/* common.css */

body {
  background: #fff;
  color: #333;
  font-size: 16px;
}

.cm-nav {
  width: 100%;
  height: 50px;
  color: #fff;
  background: #333;
}
登入後複製

我们在页面css可以这样用:

/* index.css */

.g-index {
  background: #fff;
  color: #333;
  font-size: 16px;
}

.cm-nav {
  width: 1000px;  /* 样式覆盖 */
  margin: auto;  /* 样式增加 */
}
登入後複製

状态

我们在上面讲前缀的时候,提到过一个前缀z-,我们说它可以用来表示状态。一个模块是可以有 状态 的,当然,这里说的不是状态好状态差的意思(模块还成精了~),这里指的是有多种表现形式,我们举例来说,一个弹窗模块m-dialog,它应该至少具备两种状态:显示和隐藏(关闭)。我们用关键字 active 来表示这两种状态,添加z-active类表示显示,不加表示隐藏。如下:

/* index.css */

.m-dialog {
    display: none;
}

.m-dialog.z-active {
    display: block;
}
登入後複製
<!-- index.html -->

<!DOCTYPE html>
<html>
<head>
  <title>index</title>
</head>
<body>
  <p class="g-index">
    <p class="g-bd">
      <p class="m-dialog">
        这是一个未激活的弹窗,你看不到!
      </p>
      <p class="m-dialog z-active">
        这是一个已激活的弹窗,你看得到!
      </p>
    </p>
  </p>
</body>
</html>
登入後複製

弹窗一个比较有代表性的例子,另一个典型的例子是按钮,用过bootstrap的人都知道,按钮btn只需要相对应添加几个状态类,就可以有不同的配色方案,应付不同的场景需要,这其实就是我们的z-的含义。z-是很常用的,我们应该把我们的模块设计得尽量满足多种可预见的需求,而不是每次都在页面去定制和覆盖基本样式。

总结

到目前为止,我们已经定制了一套基于规范的css模块化生产方式,虽然并不完美,但这却也是一套简单的、零工具、零成本的解决方案,适用于任何项目。

可以看出,我们这里所谓的模块化,其实是规范化的子集,通过制定了一套规范,才产生了模块。所以css的模块化过程其实是css规范化的过程。

事实上,由于css本身并不是一门语言,不具备语言的特性,我们只有借助其他方式和工具,才能达到模块化的目的。而目前为止,我们还只是停留在规范的约束方式上,内容看起来比较low :),没关系,下一节我们会开始介绍【css预处理语言的模块化实践】。要知道,对于早已习惯sass编程的我,也是闷着一大口气好不容易才写到了这里的。。。

想必你也留意到了文中多处提到“手打css”这一说法,其实这只是对传统css编程方式的一种戏称,说实话有哪种编程不是手打的,难不成用脚么?哈哈。但是说实话,有了css预处理,模块化才能算得上真正意义的模块化,模块化的意义才凸显出来,因为我们所有的思考与努力,机关算尽,最终的目的都只有一个——提高工作效率。

预告

css预处理语言的出现是一个十分重要的阶段,它直接推进了css的发展,改变了长久以来css的编程方式。

我们来瞥一眼sass:

// index.scss

@import &#39;./common/normalize&#39;;
@import &#39;./common/common&#39;;
@import &#39;./common/mixin&#39;;

.g-index {
  @include m-nav;
  @include m-news;
  @include m-copy_right;

  .g-hd {
    .m-nav {
      width: 100px;
      margin: auto;
    }
  }

  .g-bd {
    .m-news {
      margin-top: 20px;
    }
  }

  .g-ft {
    .m-copy_right {
      width: 100px;
      margin: auto;
    }
  }
}
登入後複製

sass的选择器嵌套写法是不是亮瞎双眼?文件直接导入是不是很方便?还有变量?还能写函数???

下一节,【css预处理语言的模块化实践】我们来看css预处理语言如何使模块化更加美好。

以上是從css談模組化的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

vue中placeholder是什麼意思 vue中placeholder是什麼意思 May 07, 2024 am 09:57 AM

vue中placeholder是什麼意思

vue中空格怎麼寫 vue中空格怎麼寫 Apr 30, 2024 am 05:42 AM

vue中空格怎麼寫

vue中怎麼取得dom vue中怎麼取得dom Apr 30, 2024 am 05:36 AM

vue中怎麼取得dom

js中span是什麼意思 js中span是什麼意思 May 06, 2024 am 11:42 AM

js中span是什麼意思

js中rem是什麼意思 js中rem是什麼意思 May 06, 2024 am 11:30 AM

js中rem是什麼意思

vue中引入圖片的方法 vue中引入圖片的方法 May 02, 2024 pm 10:48 PM

vue中引入圖片的方法

span標籤的作用是什麼 span標籤的作用是什麼 Apr 30, 2024 pm 01:54 PM

span標籤的作用是什麼

js中prompt怎麼換行 js中prompt怎麼換行 May 01, 2024 am 06:24 AM

js中prompt怎麼換行

See all articles