• 我的liunx开发环境的配置之路


      相信有不少人和我一样,虽然是做纯linux开发,但并不排斥windows,并且喜欢在windows下面的使用各种好用的工具来让linux的编程工作变得更加方便。实际上每一个系统都有他的过人支持,windows拥有无数的好用的窗口程序,但windows的命令行工具基本算是退化到了和人类指甲盖的一样的境地。 linux正好想法,拥有无所不能的终端和无数的命令,但他的图形界面和用户体验的确还有很长的路要走。至于苹果的mac,我们可以说他即拥有比拟甚至超远(在部分人的眼里)windows的图形界面体验,也有拥有和linux一样好用的终端工具。唯一可惜的它比较封闭并且很多东西自成一体。对我而言这些系统的地位都是平等的,无非是黑猫白猫的区别。因此,在linux开发工作上我选择的是多系统结合的路线,主机系统使用更加便捷的win7,使用虚拟机来搭建linux开发环境。

      其实这样的搭配还有很多其他选择的理由,比如,虽然在很多人眼里虚拟机没有纯linux系统运行的快速而纯净, 关于速度,其实已经成为过去时了,如果你有一个在性能上等同或超越第三带台式机i3性能的CPU、一个最新的vmware或virtualbox和一个流行而较新的linux发行版,我想你会发现,虚拟机在新性能上的损失几乎不会会给你的工作带来任何麻烦。提高效率最好办法是弄一个i7级别的CPU,而不是否用了虚拟机。关于系统的纯净度的问题其实也只是一个你是否愿意花点时间来解决的问题。如果使用虚拟机,你要面对的无非是虚拟机的网络和主机怎么拓扑,虚拟机的文件和主机怎么共享,虚拟机的图形界面怎样增强,usb设备怎样给虚拟机使用等问题,实际上这些问题,只要你使用一个流行的linux发行版作为开发环境(尤其是像ubuntu这种什么问题一搜索答案一大把的系统),都将不是问题。其中尤其是网卡的共享和拓扑,我在最初使用的一两年一直都觉得虚拟机的网络容易出现问题,出现一些网络上的问题我也总是首先怀疑是虚拟机产生的网络环境导致,可是后来我发现我错了,实践证明,你几乎不应该怀疑虚拟机虚拟出来的网卡的任何特性。出现问题的原因基本上都是你没配置正确。

      好了,关于虚拟机的优劣不是今天讨论论的主题,鉴于今天写的内容和直接和虚拟机有关,前面不免多花了点文字在为虚拟机平反上,主要是希望用纯系统的人看到这篇文章时不要在心里说“linux开发还用虚拟机,真没出息”。人类创造的东西总是在进步的,虚拟机也不例外。

      用虚拟机来开发的时候会遇到一个使用方法上的问题,有两个主要的方案可供选择,第一个方案是使用虚拟机登录图形界面,直接全屏或窗口模式在虚拟机中的图形界中工作。这样做的好处是不会出现剪切板共享的问题,因为任何一个虚拟机软件都有一个在主机和客户机之间共享剪切板的功能,当然前提是你要在配置中开启它。可是如果你使用虚拟机的图形界面来做开发,你将会面临一个win7和ubuntu之间控制权的切换问题,该问题主要表现在该由谁来接管我们唯一一个鼠标和键盘,通常最好的解决办法是设置一个全局的切换热键来让控制权在两个系统之间切换,vmware默认使用ctrl+alt组合键来切换,virtualbox默认使用右边的ctrl来切换。无论使用那一个虚拟软件,频繁的使用这个切换热键是躲避不了的。当然,鼠标流的同学完全可以通过窗口模式来处用虚拟机并且使用鼠标来在两系统键快速切换。所以实际上这个问题对于鼠标党来说不是太大的问题,可惜的是,我是个键盘党。键盘党们使用虚拟机图形界面可能遇到的第二个问题是alt键在虚拟机中反应问题,这个问题的具体表现是,如果你的vim设置了不少alt组合快捷键,你将发现在linux终端的vim中操作这些快捷键,他们往往有很大的概率给识别成了 Esc 和组合键第二个键的两键输入。这个问题经验证得出是虚拟机和gnome-termal终端对键盘输入的处理问题,不论用vmware还是virtualbox,键盘的输入总是先到windows再有虚拟机软件传递到虚拟机。这个中场景和纯的linux主机直接接管键盘硬件总会是有写出入的,而这个出入正中了gnome-terminal终端对键盘流处理的下怀,于是gnome-terminal有大几率将Alt键识别成了Esc键,至于为什么是被错在的识别成Esc键而不是别的的键,那就得了解一点系统对Alt组合键处理的历史渊源了。有兴趣的话多百度谷歌就明白了。如果你用的linux发行版不是ubuntu而是opensuse或者linux_mint的KDE版等或者你用把ubuntu的图形界面切换到了KDE版本也将不会遇到这个问题, 因为KDE系统的默认终端konsole在虚拟机中对键盘流的处理没有这个bug(至少我认为这是个bug)。所以解决这个问题的最简单办法是放弃使用gnome-terminal而该用konsole或直接放弃使用ubuntu。可惜的是这样也是有缺点的,放弃ubuntu而改用KDE的桌面在使用习惯上将会有一个比较大的转变,KDE桌面的灵活性要比不gnome强多了,你需要花一些时间来适应和打磨KDE桌面,实际上KDE4对虚拟机的增强功能支持要比gnome好不少。到这里其实使用KDE桌面都是正面的好处,但有一个比较严重的负面问题是konsole终端对字体的渲染真的没有gnome好,ubuntu中gonme-termail终端的字体渲染的锐利而清晰,而konsole的字体却总是让人觉得多一点模糊。这个模糊感对一天到晚使用终端的linux码农来说是很不爽的,至少对于我来说这样。唉,上帝总是给你惊喜的同时不忘给你一记耳光。

      除了主机和虚拟机之间的控制权键盘切换不便和在linux图形界面中使用终端总是不尽人意两个问题之外,还有一个重要问题导致了我最近放弃了直接在虚拟机中使用图形界面。那就是我最喜欢的 yahei_mono 混合字体在linux终端都表现完全和windows下面不是一个级别,虽然我有找到过修改版的yahei_mono for linux版字体,但这个字体表现依然不如windows下面令人愉悦。

      于是,我最终还是放弃了直接使用linux的图形界面来操作虚拟机,转而使用的是在windows下面通过ssh登录虚拟机的方式来管理理我的linux系统。这样做直接解决了上面提到的三个问题:由于使用了windows下原生的ssh软件来登录linux,两个系统键切换的问题就没有,因为全都是在windows下控制的。alt组合键在vim中不灵光的问题也没有出现在ssh远程登录的方式上。我终于可以在win7里愉快的使用原生为windows而合成的yahei_mono字体了。

      如前所述,上帝总是在给你惊喜的同时不忘给你一记耳光,ssh登陆的方式有它的优点的同时很快我便发现这样使用缺点。我选择的第一个用来ssh登录虚拟机的工具软件是大名鼎鼎的putty。putty的优点是小巧高效兼容性好。但很快它便暴露了他的第一个缺点,不支持终端背景透明。由于我习惯了在gnome终端中获得的对我而言比较舒服的背景稍透明的效果,putty上乌黑一片的背景底色让我感到很是压抑。要只要人压抑久了很得抑郁症的,这是个大问题!好在有需求往往就有行动,我的这个需求似乎是全世界唯一的愿望,我很快就找到可以支持的透明效果的putty增强版软件:pietty。这个软件不光可以完美实现背景透明,更加令人爽快的是他还可以实现窗口框架和菜单栏的完全隐藏,在windows下面使用一个连关闭按钮都找不到的半透明窗口来操作另一个linux的系统,光派头都是很高大上的。什么?你问我没有关闭按钮怎么关闭呢?快捷键啊!!!这里顺便隆重推荐windows下面设置快捷键的神器(autohotkey)和用它实现的好用子项目 vimdesktop!最后pietty还有一个牛逼的功能,所有的配置都可以设置成存储在软件同目录的pitetty.ini中,这将同时实现了配置的备份、软件绿化和便携化。

      使用的ssh登录来控制linux还有很多可以解决的问题:第一个是你只能通过终端来操作linux任何图形界面的操作都不支持,好在linux和开发相关的90%的工作都可以在终端中完成(往往90%的工作是只能在终端中完成)。其他的一些需求,诸如浏览器,调试工具的使用等,大多数都可以在windows下面直接进行(windows下面的使用的图形软件往往要比linux下面好用)。最后还有少之又少的一些必须在linux图形界面中完成的工作就切换到虚拟机的图形界面下进行吧。第二个可以解决问题是默认情况下一个ssh连接只能产生一个终端。这对于一天到晚使用终端来了开发的工程师来说往往是不够的。有两个办法可以解决他,第一个最简单,多开几个pietty来产生多个ssh连接即可。这样做的缺点是你不得不每天工作之前都去多开几个pietty。第二个就稍微高端一点了:使用终端多窗口管理软件来在一个终端中管理多个shell进程。这种终端多窗口管理软件的鼻祖就是screen命令,有兴趣多百度谷歌把。不过screen毕竟太老了,很多功能是不完善的,想要玩爽终端里的多shell切换,还是要请出后起之秀tumx。关于tumx的配置和使用还是要花点精力的。这里就不多说了,有兴趣就多百度谷歌吧。这里顺序贴出我花了一些时间收集来的.tmux.conf 配置文件和.bashrc中和tmux有关的配置吧。.bashrc中的配置实现了ssh登录后自动创建4个shell窗口的功能。

    .tmux.conf 收集的配置:

    # tmux 2.2 在ubuntu中存在窗口分割线在vim中翻页时断线的问题
    # " vim:set ft=screen: 显示vi-cope模式下的映射 tmux list-keys -t vi-copy
    setw -g utf8 on
    # escape-time=0提高了esc键在vim中的反应速度,非常重要的配置
    set -g escape-time 0
    # index从1开始
    set -g base-index 1
    set -g pane-base-index 1
    # 可以自动调节窗口index
    set -g renumber-windows on
    # 远程终端的标题加入当前运行的程序名
    # setw -g automatic-rename off
    set -g set-titles on
    set -g set-titles-string '#W-tmux'
    # 历史缓冲大小和终端类型设置
    set -g history-limit 81920
    # set -g default-terminal "screen-256color"
    # tmux的复制模式使用vi模式以及一些好用的映射
    setw -g mode-keys vi
    bind -t vi-copy v begin-selection
    bind -t vi-copy / search-backward
    bind -t vi-copy ? search-forward
    bind -t vi-copy space page-up
    bind -t vi-copy m page-down
    bind -t vi-copy y copy-pipe 'xclip -in -selection clipboard'
    
    bind -  splitw -v
    bind   splitw -h
    bind ; selectp -R
    bind q  killp
    bind z  kill-session
    
    # pane分割条,状态栏,消息显示,复制模式等显示风格设置(主题)
    #status bar using utf-8
    set -g status-utf8 on
    set-option -g status-position top
    # modes
    # setw -g mode-fg colour34
    # setw -g mode-bg colour233
    # messages
    set -g message-fg colour221
    set -g message-bg colour234
    # panes
    set -g pane-border-bg colour234
    set -g pane-border-fg colour234
    set -g pane-active-border-bg colour234
    set -g pane-active-border-fg colour234
    # statusbar
    set -g status-fg colour253
    set -g status-bg colour234
    set -g status-left ""
    set -g status-right "#[bg=colour237]%H:%M %a %m-%d[#S]"
    setw -g window-status-fg colour232
    setw -g window-status-bg colour251
    setw -g window-status-current-fg colour232
    setw -g window-status-current-bg colour163
    setw -g window-status-format "#I:#W"
    setw -g window-status-current-format "#I:#W"
    
    # 使能tmux的鼠标模式
    # for tmux version > 2.0
    # set -g mouse on
    # for tmux version < 2.0
    # setw -g mode-mouse on
    # setw -g mouse-resize-pane on
    # setw -g mouse-select-pane on
    # setw -g mouse-select-window on
    
    # bind PageUp copy-mode -e
    # bind PageDown copy-mode -e
    # set-window-option -g exit-copy-past-bottom on
    # 开启window事件提示
    # setw -g monitor-activity on
    # set -g visual-activity on

    .bashrc中实现ssh登录自动登录tmux并创建4个shell窗口的配置:

    #tmux auto login, mast add it at last of bashrc
    # DISPLAY的默认值也为:0,但在ssh登录的时候这个环境变量默认是不设置的
    # 这里显示的将其设置为:0 可以实现本地同过ssh登录本地的虚拟机后X剪切板和windows
    # 连接能力,但这样设置在远程登录时无效,远程登录要实现X剪切版和windows的共享,
    # 必须通过Xmanager等完整的Xserver服务。
    export DISPLAY=:0
    if [ "$SSH_CONNECTION" != '' -a "$TERM" != 'linux' ]; then
        export TERM='xterm-256color'
        if [ ! $TMUX ];then
            tmux has -t 0 1>/dev/null 2>/dev/null
            if [ $? = 0 ];then
                tmux -2 a
            else
                tmux new -d
                tmux neww
                tmux neww
                tmux neww
                tmux selectw -t 2
                tmux -2 a
            fi
        fi
    fi

    注意:

    * 只有ssh登录时才会展开4个shell哦, 直接在虚拟机中的开打终端将不会调用tmux

    * .tmux.conf中配置了窗口标签在终端顶部,这样更加符合现在流行的多标签页面展示效果

    * tmux的快捷键本身是比较蹩脚的,不过我们可以通过autohotkey来实现将更加方便的快捷映射到tmux中常用快捷键上来,其中最实用的映射自然是多窗口之间的切换的快捷键

      使用pietty的第三个问题是pietty不支持utf-8编码中的一些特殊字符的显示,这个问题在日常工作中其实影响不大,也就是那么些极其不常用的字符无法显示而已。不过这个问题对我来说影响上最为明显地方有两个:一个是 tmux的窗口分割线无法正常显示。 另一个是用我用vim的ydt.vim插件来查询英文单词解释时单词的发音中的部分音标字符无法显示。其实这个问题和字体也是有关系的,如果你使用了一个字符很全的字体,pietty估计也可以显示这些特殊字符。可惜我yahei_mono并没没有包含这些特殊字符。

        特殊字符无法显示是一个使用pietty的小小遗憾,有没有解决的办法呢,答案是有的,方法就是用xshell来代替pietty。 首先来看一下xshell的一些特点:xshell是xmanager套装的一部分,是一个专门的telnet、ssh、串口等登录工具。经个人实践,xshell拥有所以pietty特性,包括背景透明度调节、xmanager套件的绿化,配置文件的备份等。唯一一个pietty拥有但xshell没有的功能就窗口框架隐藏。xshell拥有一个我个人觉得牛逼到独一无二的功能就是用他内置的字体来显示那些很多字体都无法显示的特殊字符,其中包括linux的line drow扩展字符和音标。要实现这些特殊字体的显示只要勾选如下两个配置选择即可(使用内置的字体画线符、使用内置的字体,以支持powerline):

      这篇文章的最后一个主题是一个相当实用而重要的功能实现:怎样在使用ssh终端中实现linux剪切和windows剪切之间去共享!!!

      相信只要正真用过ssh登录linux主机(包括登录本地的虚拟机或远程服务器主机)并使用过vim来做过任务的人都会遇到这个问题。你将很快发现,你在windows中复制的内容想粘贴到linux中去或者从linux的vim中复制一些内容到windows上来总有那么一点不方便。为什么说是不方便呢。因为,我们依然可以勉强实现这个功能,实现的方法就是借助在xshell(或者pietty)中使用鼠标来操作,windows复制的内容在xshell中用鼠标粘贴就可以粘贴到linux,或者在当前xshell显示的内容中用鼠标选择一段,就可以复制到windows剪切板中。不过这种方式可不是什么好的办法,xshell的鼠标粘贴功能的实现原理是由xshell来帮你将windows剪切板的内容挨个通过模拟键盘输入的方式发送到xshell的远程机的shell上。这样的粘贴方式在粘贴内容到shell命令行中没什么问题,不过如果要粘贴内容到vim中可以就有些问题了。你将很快发现,这些粘贴的内容在粘贴时是一个字符一个字符的发送到vim中的,这如同你用键盘敲入这些内容。只不过粘贴的自动输入要比你手动输入快的多而已。vim在终端模式下本身就有一个缺点,这个缺点无论你是用什么样的方式登录终端,只要是在终端中使用vim就会存在。那就vim无法区分从终端粘贴来的内容和键盘输入的内容。这将导致你粘贴过程在vim中会被当作键盘输入一样处理。这也是为什么vim要设置一个 set paste 操作命令的原因(:set paste等于是通知了vim后面的动作是粘贴,请不要做多余的处理)。显然,如果你粘贴的内容没有包含你设置的特殊的快捷映射或者内容比较短的时候是没有问题的。不过如果你粘贴的内容很长的话就蛋疼了,首先出粘贴的过程比较慢,其次是内容过多很难保证不包含vim会自动处理的字符流。当然,你可以通过在粘贴前设置 set pastetoggle 粘贴后再 set pasteoggle 方式来避免vim多余处理粘贴内容的问题。你甚至可以通过设置set pastetoggle到一个快捷键上然后用autohotkey自动在粘贴之前和之后自动发送这个快捷键的方式来一键全自动粘贴。不过这个方式依然是那么的让人感到一丝蛋疼。好吧,粘贴的过程虽然会蛋疼,但至少还可以解决,从linux复制内动到windows可就不是蛋疼一下就解决的问题了。xshell(包括 pietty)的辅助原理是从终端窗口输出中抽取内容来直接复制到windows剪切板中,这就是意味着你只能复制那些在当前窗口界面中显示的文字,那些所有没有显示出的内容,你都无法一次性复制, 比如你想复制一个shell命令的所有输出,这输出占了5页,那么你将不得不翻一页复制一次这样连续五次的操作,你还要关心翻页的临界点是否有行重叠,在vim中复制也是如此。这是一个何其蛋疼的问题啊!!!

      问题已经很明确了,有没有办法解决呢,答案是有的,而且非常的巧妙,巧妙到我实现的时候都觉得莫名其妙!

      解决的办法就是实现windows系统剪切板和linux系统剪切板的共享,这种剪切板共享的实现有两种风方式:

    1. 利用xmanger提供的xserver服务并勾自动选剪切板共享来实现,这种实现的方式的原理就是linux系统的X window架构本身就实现的剪切板和图形界面的远程交互,关于X window架构,感兴趣请自行百度谷歌。xshell的xserver提供了一个自动同步本地windows剪切板和远程Xclient剪切板的方式。由于这种方式需要linux的X架构参与,因此,需要配置并开启linux的X window的远程接口。好在,ubuntu的默认配置已经开启这这些功能。所以如果你用的ubuntu,就不用配置啦。xshell这边自然也是要做一些配置才能实现剪切板共享和完整的xserver服务的。首先是,你需要启动xmanager服务。其次开启xmanager的剪切板共享功能,这个功能藏的不是一般的深,我也是花的好长的时间才找到的(对xmanger为什么设计成这样表示无语),下面是具体配置记录:

    双击Xstart启动Xstrat配置:

    点击取消来关闭弹出的新建会话窗口,点击"高级..."

    点击 "配置(c)..."

    点击高级选项卡

    看到"自动复制粘贴"配置没?像这个页面中显示的样子配置它就可以开启xmanger的windows和linux剪切板自动同步功能了!!!

    到这里呢,你终于开启了xshell的剪切板共享功能了, 从此,在ssh的终端命令行上, 你可以继续使用widnows的Ctrl-v或者xshell的右键粘贴功能来粘贴内容,在vim只要使用快捷键 "+y 你就就能神奇的将windows剪切版内容粘贴到vim中。当然,这种粘贴方式没有任何副作用,vim会处理很快很准确。如果你觉得 "+y  太麻烦,没关系,.vimrc中映射一个爽一点的快捷键就行了。至于复制那就更爽了,vim中你可以想怎么复制就怎么复制,只要记得将内容辅助到 "+" 剪切版就可以了自动传递到windows剪切板上来,如果想复制终端命令行的内容,一屏以内直接鼠标选择即可, 哦对,最后需要提醒的是, vim默认是没有"+"号剪切板的,因为这个剪切板在vim中代表着X window的剪切板,而vim认为X window剪切板属于图形界面的一部分,因此vim没有在终端版本中集成,如果你想用vim的 "+" 号剪切版本,使用 sudo apt-get install gvim 来安装linux下面的gvim就可以了。

      这个方法是一个无论本地ssh登录虚拟机还是远程ssh登录linux服务器都可以实现系统剪切共享功能的方法,第二个办法只适用于本地登录虚拟机,因此,该这方法还是很重要的。 其实这个方法使用的时候还有一个小小的注意事项(至少最新的xmanger5依然存在这个bug),那就是在win7下面启动xmanager后使用xshell通过ssh登录linux后每打开关闭一次vim,win7的上xmanager就会崩溃并重启一次,而这个崩溃重启的过程虽然不会影响终端使用但会导致win7任务栏中的xmanager图标不断增加,就像下面的样子:

    你只有在将鼠标指向这些多余的图标时他们才会消失,这个问题引发的原因是vim每次退出的时候xmanager会崩溃,崩溃的原因似乎是xmangager提供的xserver和linux的Xclient没有完整的建立连接,后来我找到了一个办法可以间接的解决这个问题。那就是在使用ssh连接到linux系统上后通过终端启动一个图形程序并关闭就可了(我一般会在登录后启动并关闭一次gvim来出现xserver和xclient之间的完整连接,启动gvim后你将看到X window架构最牛逼能力:gvim图形界面直接在winddows下面出现了!)。

    2. 这种方式是我在一次偶然的配置中发现的,估计也算是全网首发了,这个方式配置简单,不需要启动xmanager,不需要配置Xstart, 没有Xmanger的关闭vim崩溃bug, 你甚至不需要下载安装配置完整的Xmanger套件,而只需要是一个xshell就可以实现虚拟机之间的剪切板共享能力!!!

    好了,下面是公布该方法配置过程的时候,其实如果你认真的读完了这篇又臭又长的个人笔记式的文章后,你可以在文章之前的地方找到答案,没错, 就是在 .bashrc中关于tmux的那段配置中:

    # DISPLAY的默认值也为:0,但在ssh登录的时候这个环境变量默认是不设置的
    # 这里显示的将其设置为:0 可以实现本地同过ssh登录本地的虚拟机后X剪切板和windows
    # 连接能力,但这样设置在远程登录时无效,远程登录要实现X剪切版和windows的共享,
    # 必须通过Xmanager等完整的Xserver服务。
    export DISPLAY=:0

    看到没有, 就一句配置 : exprot DISPLAY=:0

    我已经不记得我是怎么样倒腾出这个配置并发现他可以实现虚拟机和win7之间的系统剪切板共享的功能了,我至今也依然没有想明白这个配置能工作的原理的。但事实就摆在眼前:it work!

    只要你在.bashrc中加入这段配置(我只在ubuntu中实验成功,不保证其他linux系统也可以实现相同的效果),从此,你就会拥有一个可以在win7主机和ubuntu虚拟机之间直接共享系统剪切板的xshell或者pietty!!!

    后记:最近有发现了xshell的一个问题:双击鼠标选则单词在默认;情况下对单词的定义是比精准的那种,然而我在日常使用中发现对终端单词的选择往往是需要的是选择两个空格之间的“大单词”,pietty默认就是只以空格作为单词分割符的,因为这个问题,有段时间我还用回了pietty,不过在后来在一次偶然的配置中我找到了xshell设置单词分割字符的位置:

    点击 菜单栏->工具->选项->切换到”鼠标和键盘“选项卡,得到如下界面:

    看到双击指定选择时使用的分隔符没,他的默认设置是: :;~`!@#$%^&*()-=+|[]{}'",.<>/?,这里我将其他所有字符都删除了,只留下了空格:  , 注意:第一个""明显是一个转义符,后面跟的一个空格代表着真正的空格。这样设置后,在xshell中双击就会以空格作为单词分割符来选择单词啦,更方便的是,如果你真的有特殊的字符需要作为分割符,直接在这里添加一下就好。不过,就算这样,xshell还是一个小小的bug无法解决:vim中使用鼠标双击无法正确的选择单词,这个功能在pietty中是完全可以正常工作的。好在,vim我很少不会用到鼠标。

    最后的最后,秀一张各种配置完成后实现的Xshell效果图吧(改图包括一些重点的配置:xshell背景透明、ssh登录时自动登录tmux并创建4个终端窗口、终端窗口标签列表在顶端显示、xshell实现系统剪切板共享、xshell正常显示窗口分割线和音效、vim存在"+"号剪切板):

  • 相关阅读:
    使用Mint-UI的Loadmore实现上拉加载更多和下拉刷新
    JavaScript的日常所得
    web网站性能优化整理
    ArrayBuffer
    Blob
    FormData
    FileReader
    websocket的实践
    Vue CLI 3的Vue.config.js
    css行高line-height的一些深入理解及应用
  • 原文地址:https://www.cnblogs.com/pangchol/p/5062115.html
Copyright © 2020-2023  润新知