<font id="zqva1"></font>
<rt id="zqva1"></rt>
  • <tt id="zqva1"></tt>
    <cite id="zqva1"></cite>

    <cite id="zqva1"><noscript id="zqva1"></noscript></cite>
      <rp id="zqva1"><meter id="zqva1"></meter></rp>

        <cite id="zqva1"></cite>
          <b id="zqva1"></b>
          <rp id="zqva1"></rp>
          <cite id="zqva1"></cite>

          <rt id="zqva1"></rt>

        1. <rp id="zqva1"></rp>

          gulpjs的使用,前端構建工具gulpjs的使用介紹及技巧

          時間:?2017-12-18閱讀:?834標簽:?gulp

          gulpjs是一個前端構建工具,與gruntjs相比,gulpjs無需寫一大堆繁雜的配置參數,API也非常簡單,學習起來很容易,而且gulpjs使用的是nodejs中stream來讀取和操作數據,其速度更快。如果你還沒有使用過前端構建工具,或者覺得gruntjs太難用的話,那就嘗試一下gulp吧。


            1、gulp的安裝

            首先確保你已經正確安裝了nodejs環境。然后以全局方式安裝gulp:

            npm install -g gulp
            

            全局安裝gulp后,還需要在每個要使用gulp的項目中都單獨安裝一次。把目錄切換到你的項目文件夾中,然后在命令行中執行:

            npm install gulp
            

            如果想在安裝的時候把gulp寫進項目package.json文件的依賴中,則可以加上--save-dev:

            npm install --save-dev gulp
            

            這樣就完成了gulp的安裝。至于為什么在全局安裝gulp后,還需要在項目中本地安裝一次,有興趣的可以看下stackoverflow上有人做出的回答:why-do-we-need-to-install-gulp-globally-and-locallywhat-is-the-point-of-double-install-in-gulp。大體就是為了版本的靈活性,但如果沒理解那也不必太去糾結這個問題,只需要知道通常我們是要這樣做就行了。


            2、開始使用gulp

            2.1 建立gulpfile.js文件

            就像gruntjs需要一個Gruntfile.js文件一樣,gulp也需要一個文件作為它的主文件,在gulp中這個文件叫做gulpfile.js。新建一個文件名為gulpfile.js的文件,然后放到你的項目目錄中。之后要做的事情就是在gulpfile.js文件中定義我們的任務了。下面是一個最簡單的gulpfile.js文件內容示例,它定義了一個默認的任務。

            var gulp = require('gulp');
            gulp.task('default',function(){
                console.log('hello world');
            });
            

            此時我們的目錄結構是這樣子的:

            ├── gulpfile.js
            ├── node_modules
            │ └── gulp
            └── package.json

            2.2 運行gulp任務

            要運行gulp任務,只需切換到存放gulpfile.js文件的目錄(windows平臺請使用cmd或者Power Shell等工具),然后在命令行中執行gulp命令就行了,gulp后面可以加上要執行的任務名,例如gulp task1,如果沒有指定任務名,則會執行任務名為default的默認任務。


            3、gulp的API介紹

            使用gulp,僅需知道4個API即可:gulp.task(),gulp.src(),gulp.dest(),gulp.watch(),所以很容易就能掌握,但有幾個地方需理解透徹才行,我會在下面一一說明。為了避免出現理解偏差,建議先看一遍官方文檔

            3.1 gulp.src()

            在介紹這個API之前我們首先來說一下Grunt.js和Gulp.js工作方式的一個區別。Grunt主要是以文件為媒介來運行它的工作流的,比如在Grunt中執行完一項任務后,會把結果寫入到一個臨時文件中,然后可以在這個臨時文件內容的基礎上執行其它任務,執行完成后又把結果寫入到臨時文件中,然后又以這個為基礎繼續執行其它任務...就這樣反復下去。而在Gulp中,使用的是Nodejs中的stream(流),首先獲取到需要的stream,然后可以通過stream的pipe()方法把流導入到你想要的地方,比如Gulp的插件中,經過插件處理后的流又可以繼續導入到其他插件中,當然也可以把流寫入到文件中。所以Gulp是以stream為媒介的,它不需要頻繁的生成臨時文件,這也是Gulp的速度比Grunt快的一個原因。再回到正題上來,gulp.src()方法正是用來獲取流的,但要注意這個流里的內容不是原始的文件流,而是一個虛擬文件對象流(Vinyl files),這個虛擬文件對象中存儲著原始文件的路徑、文件名、內容等信息,這個我們暫時不用去深入理解,你只需簡單的理解可以用這個方法來讀取你需要操作的文件就行了。其語法為:

            gulp.src(globs[, options])
            

            globs參數是文件匹配模式(類似正則表達式),用來匹配文件路徑(包括文件名),當然這里也可以直接指定某個具體的文件路徑。當有多個匹配模式時,該參數可以為一個數組。
            options為可選參數。通常情況下我們不需要用到。

            下面我們重點說說Gulp用到的glob的匹配規則以及一些文件匹配技巧。
            Gulp內部使用了node-glob模塊來實現其文件匹配功能。我們可以使用下面這些特殊的字符來匹配我們想要的文件:

            • * 匹配文件路徑中的0個或多個字符,但不會匹配路徑分隔符,除非路徑分隔符出現在末尾
            • ** 匹配路徑中的0個或多個目錄及其子目錄,需要單獨出現,即它左右不能有其他東西了。如果出現在末尾,也能匹配文件。
            • ? 匹配文件路徑中的一個字符(不會匹配路徑分隔符)
            • [...] 匹配方括號中出現的字符中的任意一個,當方括號中第一個字符為^或!時,則表示不匹配方括號中出現的其他字符中的任意一個,類似js正則表達式中的用法
            • !(pattern|pattern|pattern) 匹配任何與括號中給定的任一模式都不匹配的
            • ?(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或1次,類似于js正則中的(pattern|pattern|pattern)?
            • +(pattern|pattern|pattern) 匹配括號中給定的任一模式至少1次,類似于js正則中的(pattern|pattern|pattern)+
            • *(pattern|pattern|pattern) 匹配括號中給定的任一模式0次或多次,類似于js正則中的(pattern|pattern|pattern)*
            • @(pattern|pattern|pattern) 匹配括號中給定的任一模式1次,類似于js正則中的(pattern|pattern|pattern)

            下面以一系列例子來加深理解

            • * 能匹配 a.js,x.y,abc,abc/,但不能匹配a/b.js
            • *.* 能匹配 a.js,style.css,a.b,x.y
            • */*/*.js 能匹配 a/b/c.js,x/y/z.js,不能匹配a/b.js,a/b/c/d.js
            • ** 能匹配 abc,a/b.js,a/b/c.js,x/y/z,x/y/z/a.b,能用來匹配所有的目錄和文件
            • **/*.js 能匹配 foo.js,a/foo.js,a/b/foo.js,a/b/c/foo.js
            • a/**/z 能匹配 a/z,a/b/z,a/b/c/z,a/d/g/h/j/k/z
            • a/**b/z 能匹配 a/b/z,a/sb/z,但不能匹配a/x/sb/z,因為只有單**單獨出現才能匹配多級目錄
            • ?.js 能匹配 a.js,b.js,c.js
            • a?? 能匹配 a.b,abc,但不能匹配ab/,因為它不會匹配路徑分隔符
            • [xyz].js 只能匹配 x.js,y.js,z.js,不會匹配xy.js,xyz.js等,整個中括號只代表一個字符
            • [^xyz].js 能匹配 a.js,b.js,c.js等,不能匹配x.js,y.js,z.js

            當有多種匹配模式時可以使用數組

            //使用數組的方式來匹配多種文件
            gulp.src(['js/*.js','css/*.css','*.html'])
            

            使用數組的方式還有一個好處就是可以很方便的使用排除模式,在數組中的單個匹配模式前加上!即是排除模式,它會在匹配的結果中排除這個匹配,要注意一點的是不能在數組中的第一個元素中使用排除模式

            gulp.src([*.js,'!b*.js']) //匹配所有js文件,但排除掉以b開頭的js文件
            gulp.src(['!b*.js',*.js]) //不會排除任何文件,因為排除模式不能出現在數組的第一個元素中
            

            此外,還可以使用展開模式。展開模式以花括號作為定界符,根據它里面的內容,會展開為多個模式,最后匹配的結果為所有展開的模式相加起來得到的結果。展開的例子如下:

            • a{b,c}d 會展開為 abd,acd
            • a{b,}c 會展開為 abc,ac
            • a{0..3}d 會展開為 a0d,a1d,a2d,a3d
            • a{b,c{d,e}f}g 會展開為 abg,acdfg,acefg
            • a{b,c}d{e,f}g 會展開為 abdeg,acdeg,abdeg,abdfg

            3.2 gulp.dest()

            gulp.dest()方法是用來寫文件的,其語法為:

            gulp.dest(path[,options])
            

            path為寫入文件的路徑
            options為一個可選的參數對象,通常我們不需要用到

            要想使用好gulp.dest()這個方法,就要理解給它傳入的路徑參數與最終生成的文件的關系。
            gulp的使用流程一般是這樣子的:首先通過gulp.src()方法獲取到我們想要處理的文件流,然后把文件流通過pipe方法導入到gulp的插件中,最后把經過插件處理后的流再通過pipe方法導入到gulp.dest()中,gulp.dest()方法則把流中的內容寫入到文件中,這里首先需要弄清楚的一點是,我們給gulp.dest()傳入的路徑參數,只能用來指定要生成的文件的目錄,而不能指定生成文件的文件名,它生成文件的文件名使用的是導入到它的文件流自身的文件名,所以生成的文件名是由導入到它的文件流決定的,即使我們給它傳入一個帶有文件名的路徑參數,然后它也會把這個文件名當做是目錄名,例如:

            var gulp = require('gulp');
            gulp.src('script/jquery.js')
                .pipe(gulp.dest('dist/foo.js'));
            //最終生成的文件路徑為 dist/foo.js/jquery.js,而不是dist/foo.js
            

            要想改變文件名,可以使用插件gulp-rename

            下面說說生成的文件路徑與我們給gulp.dest()方法傳入的路徑參數之間的關系。
            gulp.dest(path)生成的文件路徑是我們傳入的path參數后面再加上gulp.src()中有通配符開始出現的那部分路徑。例如:

            var gulp = reruire('gulp');
            //有通配符開始出現的那部分路徑為 **/*.js
            gulp.src('script/**/*.js')
                .pipe(gulp.dest('dist')); //最后生成的文件路徑為 dist/**/*.js
            //如果 **/*.js 匹配到的文件為 jquery/jquery.js ,則生成的文件路徑為 dist/jquery/jquery.js
            

            再舉更多一點的例子

            gulp.src('script/avalon/avalon.js') //沒有通配符出現的情況
                .pipe(gulp.dest('dist')); //最后生成的文件路徑為 dist/avalon.js
            
            //有通配符開始出現的那部分路徑為 **/underscore.js
            gulp.src('script/**/underscore.js')
                //假設匹配到的文件為script/util/underscore.js
                .pipe(gulp.dest('dist')); //則最后生成的文件路徑為 dist/util/underscore.js
            
            gulp.src('script/*') //有通配符出現的那部分路徑為 *
                //假設匹配到的文件為script/zepto.js    
                .pipe(gulp.dest('dist')); //則最后生成的文件路徑為 dist/zepto.js
            

            通過指定gulp.src()方法配置參數中的base屬性,我們可以更靈活的來改變gulp.dest()生成的文件路徑。
            當我們沒有在gulp.src()方法中配置base屬性時,base的默認值為通配符開始出現之前那部分路徑,例如:

            gulp.src('app/src/**/*.css') //此時base的值為 app/src
            

            上面我們說的gulp.dest()所生成的文件路徑的規則,其實也可以理解成,用我們給gulp.dest()傳入的路徑替換掉gulp.src()中的base路徑,最終得到生成文件的路徑。

            gulp.src('app/src/**/*.css') //此時base的值為app/src,也就是說它的base路徑為app/src
                 //設該模式匹配到了文件 app/src/css/normal.css
                .pipe(gulp.dest('dist')) //用dist替換掉base路徑,最終得到 dist/css/normal.css
            

            所以改變base路徑后,gulp.dest()生成的文件路徑也會改變

            gulp.src(script/lib/*.js) //沒有配置base參數,此時默認的base路徑為script/lib
                //假設匹配到的文件為script/lib/jquery.js
                .pipe(gulp.dest('build')) //生成的文件路徑為 build/jquery.js
            
            gulp.src(script/lib/*.js, {base:'script'}) //配置了base參數,此時base路徑為script
                //假設匹配到的文件為script/lib/jquery.js
                .pipe(gulp.dest('build')) //此時生成的文件路徑為 build/lib/jquery.js    
            

            用gulp.dest()把文件流寫入文件后,文件流仍然可以繼續使用。

            3.3 gulp.task()

            gulp.task方法用來定義任務,內部使用的是Orchestrator,其語法為:

            gulp.task(name[, deps], fn)
            

            name 為任務名
            deps 是當前定義的任務需要依賴的其他任務,為一個數組。當前定義的任務會在所有依賴的任務執行完畢后才開始執行。如果沒有依賴,則可省略這個參數
            fn 為任務函數,我們把任務要執行的代碼都寫在里面。該參數也是可選的。

            gulp.task('mytask', ['array', 'of', 'task', 'names'], function() { //定義一個有依賴的任務
              // Do something
            });
            

            gulp.task()這個API沒什么好講的,但需要知道執行多個任務時怎么來控制任務執行的順序。
            gulp中執行多個任務,可以通過任務依賴來實現。例如我想要執行one,two,three這三個任務,那我們就可以定義一個空的任務,然后把那三個任務當做這個空的任務的依賴就行了:

            //只要執行default任務,就相當于把one,two,three這三個任務執行了
            gulp.task('default',['one','two','three']);
            

            如果任務相互之間沒有依賴,任務會按你書寫的順序來執行,如果有依賴的話則會先執行依賴的任務。
            但是如果某個任務所依賴的任務是異步的,就要注意了,gulp并不會等待那個所依賴的異步任務完成,而是會接著執行后續的任務。例如:

            gulp.task('one',function(){
              //one是一個異步執行的任務
              setTimeout(function(){
                console.log('one is done')
              },5000);
            });
            
            //two任務雖然依賴于one任務,但并不會等到one任務中的異步操作完成后再執行
            gulp.task('two',['one'],function(){
              console.log('two is done');
            });
            

            上面的例子中我們執行two任務時,會先執行one任務,但不會去等待one任務中的異步操作完成后再執行two任務,而是緊接著執行two任務。所以two任務會在one任務中的異步操作完成之前就執行了。

            那如果我們想等待異步任務中的異步操作完成后再執行后續的任務,該怎么做呢?
            有三種方法可以實現:
            第一:在異步操作完成后執行一個回調函數來通知gulp這個異步任務已經完成,這個回調函數就是任務函數的第一個參數。

            gulp.task('one',function(cb){ //cb為任務函數提供的回調,用來通知任務已經完成
              //one是一個異步執行的任務
              setTimeout(function(){
                console.log('one is done');
                cb();  //執行回調,表示這個異步任務已經完成
              },5000);
            });
            
            //這時two任務會在one任務中的異步操作完成后再執行
            gulp.task('two',['one'],function(){
              console.log('two is done');
            });
            

            第二:定義任務時返回一個流對象。適用于任務就是操作gulp.src獲取到的流的情況。

            gulp.task('one',function(cb){
              var stream = gulp.src('client/**/*.js')
                  .pipe(dosomething()) //dosomething()中有某些異步操作
                  .pipe(gulp.dest('build'));
                return stream;
            });
            
            gulp.task('two',['one'],function(){
              console.log('two is done');
            });
            

            第三:返回一個promise對象,例如

            var Q = require('q'); //一個著名的異步處理的庫 https://github.com/kriskowal/q
            gulp.task('one',function(cb){
              var deferred = Q.defer();
              // 做一些異步操作
              setTimeout(function() {
                 deferred.resolve();
              }, 5000);
              return deferred.promise;
            });
            
            gulp.task('two',['one'],function(){
              console.log('two is done');
            });
            

            gulp.task()就這些了,主要是要知道當依賴是異步任務時的處理。

            3.4 gulp.watch()

            gulp.watch()用來監視文件的變化,當文件發生變化后,我們可以利用它來執行相應的任務,例如文件壓縮等。其語法為

            gulp.watch(glob[, opts], tasks)
            

            glob 為要監視的文件匹配模式,規則和用法與gulp.src()方法中的glob相同。
            opts 為一個可選的配置對象,通常不需要用到
            tasks 為文件變化后要執行的任務,為一個數組

            gulp.task('uglify',function(){
              //do something
            });
            gulp.task('reload',function(){
              //do something
            });
            gulp.watch('js/**/*.js', ['uglify','reload']);
            

            gulp.watch()還有另外一種使用方式:

            gulp.watch(glob[, opts, cb])
            

            globopts參數與第一種用法相同
            cb參數為一個函數。每當監視的文件發生變化時,就會調用這個函數,并且會給它傳入一個對象,該對象包含了文件變化的一些信息,type屬性為變化的類型,可以是added,changed,deleted;path屬性為發生變化的文件的路徑

            gulp.watch('js/**/*.js', function(event){
                console.log(event.type); //變化類型 added為新增,deleted為刪除,changed為改變 
                console.log(event.path); //變化的文件的路徑
            }); 
            


            4、一些常用的gulp插件

            gulp的插件數量雖然沒有grunt那么多,但也可以說是應有盡有了,下面列舉一些常用的插件。

            4.1 自動加載插件

            使用gulp-load-plugins
            安裝:npm install --save-dev gulp-load-plugins
            要使用gulp的插件,首先得用require來把插件加載進來,如果我們要使用的插件非常多,那我們的gulpfile.js文件開頭可能就會是這個樣子的:

            var gulp = require('gulp'),
                //一些gulp插件,abcd這些命名只是用來舉個例子
                a = require('gulp-a'), 
                b = require('gulp-b'),
                c = require('gulp-c'),
                d = require('gulp-d'),
                e = require('gulp-e'),
                f = require('gulp-f'),
                g = require('gulp-g'),
                //更多的插件...
                z = require('gulp-z');   
            

            雖然這沒什么問題,但會使我們的gulpfile.js文件變得很冗長,看上去不那么舒服。gulp-load-plugins插件正是用來解決這個問題。
            gulp-load-plugins這個插件能自動幫你加載package.json文件里的gulp插件。例如假設你的package.json文件里的依賴是這樣的:

            {
              "devDependencies": {
                "gulp": "~3.6.0",
                "gulp-rename": "~1.2.0",
                "gulp-ruby-sass": "~0.4.3",
                "gulp-load-plugins": "~0.5.1"
              }
            }
            

            然后我們可以在gulpfile.js中使用gulp-load-plugins來幫我們加載插件:

            var gulp = require('gulp');
            //加載gulp-load-plugins插件,并馬上運行它
            var plugins = require('gulp-load-plugins')();
            

            然后我們要使用gulp-rename和gulp-ruby-sass這兩個插件的時候,就可以使用plugins.rename和plugins.rubySass來代替了,也就是原始插件名去掉gulp-前綴,之后再轉換為駝峰命名。
            實質上gulp-load-plugins是為我們做了如下的轉換

            plugins.rename = require('gulp-rename');
            plugins.rubySass = require('gulp-ruby-sass');
            

            gulp-load-plugins并不會一開始就加載所有package.json里的gulp插件,而是在我們需要用到某個插件的時候,才去加載那個插件。
            最后要提醒的一點是,因為gulp-load-plugins是通過你的package.json文件來加載插件的,所以必須要保證你需要自動加載的插件已經寫入到了package.json文件里,并且這些插件都是已經安裝好了的。

            4.2 重命名

            使用gulp-rename
            安裝:npm install --save-dev gulp-rename
            用來重命名文件流中的文件。用gulp.dest()方法寫入文件時,文件名使用的是文件流中的文件名,如果要想改變文件名,那可以在之前用gulp-rename插件來改變文件流中的文件名。

            var gulp = require('gulp'),
                rename = require('gulp-rename'),
                uglify = require("gulp-uglify");
             
            gulp.task('rename', function () {
                gulp.src('js/jquery.js')
                .pipe(uglify())  //壓縮
                .pipe(rename('jquery.min.js')) //會將jquery.js重命名為jquery.min.js
                .pipe(gulp.dest('js'));
                //關于gulp-rename的更多強大的用法請參考https://www.npmjs.com/package/gulp-rename
            });
            

            4.3 js文件壓縮

            使用gulp-uglify
            安裝:npm install --save-dev gulp-uglify
            用來壓縮js文件,使用的是uglify引擎

            var gulp = require('gulp'),
                uglify = require("gulp-uglify");
             
            gulp.task('minify-js', function () {
                gulp.src('js/*.js') // 要壓縮的js文件
                .pipe(uglify())  //使用uglify進行壓縮,更多配置請參考:
                .pipe(gulp.dest('dist/js')); //壓縮后的路徑
            });
            

            4.4 css文件壓縮

            使用gulp-minify-css
            安裝:npm install --save-dev gulp-minify-css
            要壓縮css文件時可以使用該插件

            var gulp = require('gulp'),
                minifyCss = require("gulp-minify-css");
             
            gulp.task('minify-css', function () {
                gulp.src('css/*.css') // 要壓縮的css文件
                .pipe(minifyCss()) //壓縮css
                .pipe(gulp.dest('dist/css'));
            });
            

            4.5 html文件壓縮

            使用gulp-minify-html
            安裝:npm install --save-dev gulp-minify-html
            用來壓縮html文件

            var gulp = require('gulp'),
                minifyHtml = require("gulp-minify-html");
             
            gulp.task('minify-html', function () {
                gulp.src('html/*.html') // 要壓縮的html文件
                .pipe(minifyHtml()) //壓縮
                .pipe(gulp.dest('dist/html'));
            });
            

            4.6 js代碼檢查

            使用gulp-jshint
            安裝:npm install --save-dev gulp-jshint
            用來檢查js代碼

            var gulp = require('gulp'),
                jshint = require("gulp-jshint");
             
            gulp.task('jsLint', function () {
                gulp.src('js/*.js')
                .pipe(jshint())
                .pipe(jshint.reporter()); // 輸出檢查結果
            });
            

            4.7 文件合并

            使用gulp-concat
            安裝:npm install --save-dev gulp-concat
            用來把多個文件合并為一個文件,我們可以用它來合并js或css文件等,這樣就能減少頁面的http請求數了

            var gulp = require('gulp'),
                concat = require("gulp-concat");
             
            gulp.task('concat', function () {
                gulp.src('js/*.js')  //要合并的文件
                .pipe(concat('all.js'))  // 合并匹配到的js文件并命名為 "all.js"
                .pipe(gulp.dest('dist/js'));
            });
            

            4.8 less和sass的編譯

            less使用gulp-less,安裝:npm install --save-dev gulp-less

            var gulp = require('gulp'),
                less = require("gulp-less");
             
            gulp.task('compile-less', function () {
                gulp.src('less/*.less')
                .pipe(less())
                .pipe(gulp.dest('dist/css'));
            });
            

            sass使用gulp-sass,安裝:npm install --save-dev gulp-sass

            var gulp = require('gulp'),
                sass = require("gulp-sass");
             
            gulp.task('compile-sass', function () {
                gulp.src('sass/*.sass')
                .pipe(sass())
                .pipe(gulp.dest('dist/css'));
            });
            

            4.9 圖片壓縮

            可以使用gulp-imagemin插件來壓縮jpg、png、gif等圖片。
            安裝:npm install --save-dev gulp-imagemin

            var gulp = require('gulp');
            var imagemin = require('gulp-imagemin');
            var pngquant = require('imagemin-pngquant'); //png圖片壓縮插件
            
            gulp.task('default', function () {
                return gulp.src('src/images/*')
                    .pipe(imagemin({
                        progressive: true,
                        use: [pngquant()] //使用pngquant來壓縮png圖片
                    }))
                    .pipe(gulp.dest('dist'));
            });
            

            gulp-imagemin的使用比較復雜一點,而且它本身也有很多插件,建議去它的項目主頁看看文檔

            4.10 自動刷新

            使用gulp-livereload插件,安裝:npm install --save-dev gulp-livereload。
            當代碼變化時,它可以幫我們自動刷新頁面
            該插件最好配合谷歌瀏覽器來使用,且要安裝livereload chrome extension擴展插件,不能下載的請自行FQ。

            var gulp = require('gulp'),
                less = require('gulp-less'),
                livereload = require('gulp-livereload');
            
            gulp.task('less', function() {
              gulp.src('less/*.less')
                .pipe(less())
                .pipe(gulp.dest('css'))
                .pipe(livereload());
            });
            
            gulp.task('watch', function() {
              livereload.listen(); //要在這里調用listen()方法
              gulp.watch('less/*.less', ['less']);
            });
            

            轉載:無雙 - 博客園

            站長推薦

            1.阿里云: 本站目前使用的是阿里云主機,安全/可靠/穩定。點擊領取2000元代金券、了解最新阿里云產品的各種優惠活動點擊進入

            2.騰訊云: 提供云服務器、云數據庫、云存儲、視頻與CDN、域名等服務。騰訊云各類產品的最新活動,優惠券領取點擊進入

            3.廣告聯盟: 整理了目前主流的廣告聯盟平臺,如果你有流量,可以作為參考選擇適合你的平臺點擊進入

            鏈接: http://www.modern-decoration.com.cn/article/detial/254

            內容以共享、參考、研究為目的,不存在任何商業目的。其版權屬原作者所有,如有侵權或違規,請與小編聯系!情況屬實本人將予以刪除!

            文章投稿關于web前端網站點搜索站長推薦網站地圖站長QQ:522607023

            小程序專欄: 土味情話心理測試腦筋急轉彎幽默笑話段子句子語錄成語大全運營推廣

            国产精品高清视频免费 - 视频 - 在线观看 - 影视资讯 - 唯爱网