由淺入深學習webpack+vue全家桶椒功,實現(xiàn)知乎日報--webpack創(chuàng)建基本項目步驟(第四節(jié))單文件組件與vue-loader

截止上一節(jié),我們學習了webpack的四大核心思想:入口(entry)智什、出口(output)动漾、加載器(loaders)、插件(plugins)荠锭,并且初步創(chuàng)建了一個可以在本地端口運行的工程谦炬。接下來我們繼續(xù)探討學習.vue單文件組件的使用和編譯。

眾所周知节沦,Vue.js官網(wǎng)提供了組件的三種使用方法:

  1. 字符串 (例如:template: '...')
  2. <script type="text/x-template">
  3. 單文件組件 (.vue)
  • 第一種方法使用起來需要在js內(nèi)拼接DOM字符串键思,尤其是用" \ "換行的時候。
  • 第二種方法可以用于模板特別大的 demo 或極小型的應(yīng)用甫贯,但是其它情況下請避免使用吼鳞,因為這會將模板和該組件的其它定義分離開。這個方法也可以異步調(diào)用叫搁。
  • 本篇著重介紹第三種方法赔桌,它是構(gòu)建SPA常用的形式。

.vue文件的構(gòu)成

一個.vue文件包括三部分渴逻,<templtae>疾党、<script>、<style>惨奕,可以沒有<style>雪位,在根目錄下創(chuàng)建app.vue文件,快速建立vue預(yù)制模板梨撞,如下:

image.png

下面解讀一下各部分代表的意義:

  • <template></template>之間的代碼就是該組件的模板html雹洗,和正常書寫html一樣,不需要引號和換行符卧波。
  • <script></script>大家都很熟悉时肿,書寫js代碼,.vue文件通常使用ES6處理該組件的業(yè)務(wù)邏輯港粱。
  • <style></style>之間是css代碼螃成,示例中的<style>標簽使用了scoped屬性,表示這段css代碼只在該組件上有效查坪,如果不加寸宏,那么會應(yīng)用到整個項目。<style></style>還可以結(jié)合css預(yù)編譯一起使用咪惠,比如使用sass處理可以寫為:<style lang="sass"></style>

安裝依賴

使用.vue文件需要先安裝vue-loader击吱、vue-style-loader等加載器并做配置,因為要使用ES6語法遥昧,還需要安裝babel和babel-loader等加載器覆醇,使用npm進行逐個安裝:

npm install --save vue
npm install --save-dev vue-loader
npm install --save-dev vue-style-loader
npm install --save-dev vue-template-compiler
npm install --save-dev vue-hot-reload-api
npm install --save-dev babel
npm install --save-dev babel-loader
npm install --save-dev babel-core
npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-preset-2015
npm install --save-dev babel-runtime

安裝完成后朵纷,修改webpack.config.js來來支持.vue文件及ES6的解析:

//部分代碼省略
var config = {
    entry: {
        main: './index'
    },
    output: {
        path: path.join(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'index.js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: 'vue-loader',
                options: {
                    loaders: {
                        css: ExtractTextPlugin.extract({
                            use: 'css-loader',
                            fallback: 'vue-style-loader'
                        })
                    }
                }
            },
            {
                test: /\.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/  
            },
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    use: 'css-loader',
                    fallback: 'style-loader'
                })
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin('index.css')
    ]
};

vue-loader在編譯.vue文件時,會對<template>永脓、<script>袍辞、<style>分別處理,所以在vue-loader選項中多一項options來進一步對不同的語言進行配置常摧,比如對css進行處理時搅吁,會先通過"css-loader"解析,然后把處理結(jié)果再交給"vue-style-loader"處理落午。當技術(shù)棧多樣化時谎懦,可以對<template>、<script>溃斋、<style>指定不同的語言界拦,比如<template lang="pug"></template>、<script type="text/typescript"></script>梗劫、<style lang="sass"></stype>享甸,然后配置loaders就可以了。

配置babel信息

在根目錄下新建名稱為.babelrc的文件梳侨,并寫入babel配置蛉威,webpack會依賴此文件配置來使用babel編譯ES6,代碼如下:

{
    "presets": [
        "ES2015"
    ],
    "plugins": [
        "transform-runtime"
    ],
    "comments": false
}

編寫app.vue

代碼如下:

<template>
    <div>
        {{message}}
    </div>
</template>

<script>
export default {
  name: 'app',
  data() {
    return {
      message: 'This app.vue'
    };
  },
}
</script>

<style scoped>
    div {
        color: goldenrod;
        font-size: 18px;
    }
</style>

在<template>內(nèi)寫的HTML寫法通html文件完全一樣走哺,不需要加"\ "換行蚯嫌,webpack最終會把它變異成Render函數(shù)的形式。寫在<style>里的樣式割坠,已經(jīng)用插件extract-text-webpak-plugin配置過了齐帚,最終會統(tǒng)一提取并打包到index.css里妒牙,因為加了scoped屬性彼哼,這部分樣式只針對app.vue組件有效。

修改入口js文件

.vue的組件是沒有名稱的湘今,在父組件使用時可以對它進行定義敢朱。寫好了app.vue組件,就可以在入口文件index.js內(nèi)使用摩瞎。index.js代碼如下:

// 引入vue
import Vue from 'vue';
// 引入app.vue
import App from './app.vue'

// 創(chuàng)建vue根實例
new Vue({
    el: '#app',
    render: h => h(App)
})

注意:render: h => h(App)是ES6一種簡寫方式拴签,可以使用以下方式代替:

new Vue({
    el: '#app',
    render: (h) => {
      return h(App);
    }
})

或者

new Vue({
    el: '#app',
    render: function(h) {
      return h(App);
    }
})

修改index.html

在index.js中,把初始化Vue對象時掛在一個id="app"的元素上旗们,那么需要修改index.html文件蚓哩,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" href="dist/index.css">
</head>
<body>
    <div id="app"></div>
    <script src="dist/index.js"></script>
</body>
</html>

運行

執(zhí)行命令:npm run dev,這個vue工程就跑起來了上渴,效果如下:

image.png

在控制臺我們可以看到岸梨,id="app"的內(nèi)容被<div data-v-65bf5ec8="">This app.vue</div>代替喜颁,而且在index.css樣式表中對應(yīng)有

div[data-v-65bf5ec8] {
    color: goldenrod;
    font-size: 18px;
}

之所以有這段代碼,就是因為在app.vue中的<style>中加了scoped屬性曹阔。

附加代碼

在根目錄下新建一個components文件夾半开,新建title.vue和count.vue,并在app.vue中引用這兩個組件赃份,具體代碼如下:

  • //title.vue寂拆,代碼如下:
<template>
    <nav>
        <ul class="nav">
            <li
                v-for="(item, idx) in navs"
                :key="idx"
                :value="item.value"
                :class="{'active': idx === 0}"
            >
                <a href="javascript:void(0);">{{item.text}}</a>
            </li>
        </ul>
    </nav>
</template>

<script>
export default {
  data() {
    return {
      navs: [
          {
              text: '新聞',
              vaule: 'news'
          },
          {
              text: '視頻',
              vaule: 'videos'
          },
          {
              text: '生活',
              vaule: 'life'
          }
      ]
    };
  },
}
</script>

<style scoped>
    ul {
        list-style-type: none;
    }
    ul:after {
        content: "";
        display: table;
        clear: both;
    }
    ul li {
        float: left;
        padding: 10px 15px;
        font-size: 16px;
    }
    ul li a {
        text-decoration: none;
        color: #333;
    }
    ul li.active {
        border-bottom: 2px solid #299cee;
    }
</style>
  • count.vue(v-model語法糖示例),代碼如下:
<template>
    <div class="count">
        <button @click="handleDecrement">-</button>
        {{currentValue}}
        <button @click="handleIncrement">+</button>
    </div>
</template>

<script>
export default {
  data() {
    return {
      currentValue: this.value
    };
  },
  props: {
      value: {
          type: Number,
          default: 0
      }
  },
  watch: {
      currentValue(newValue) {
          this.$emit('input', newValue);
      }
  },
  methods: {
      handleDecrement() {
          this.currentValue--;
      },
      handleIncrement() {
          this.currentValue++;
      }
  }
}
</script>

<style scoped>
    .count {
        color: #999;
    }
    .count button {
        padding: 0 10px;
        text-align: center;
        line-height: 24px;
    }
</style>
  • app.vue抓韩,代碼如下:
<template>
    <div>
        <vTitle></vTitle>
        <vCount v-model="count"></vCount>
        <p>app.vue count {{count}}</p>
    </div>
</template>

<script>
import vTitle from './components/title.vue';
import vCount from './components/count.vue';
export default {
  name: 'app',
  components: {
      vTitle,
      vCount
  },
  data() {
    return {
      count: 10
    };
  }
}
</script>

<style scoped>
    div {
        color: goldenrod;
        font-size: 18px;
    }
</style>

運行工程纠永,即可出現(xiàn)如下效果:


app.gif

至此我們完成了一個最基本的vue工程。
完整代碼github地址:https://github.com/zhiyuanMain/zhihu-daily

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谒拴,一起剝皮案震驚了整個濱河市渺蒿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌彪薛,老刑警劉巖茂装,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異善延,居然都是意外死亡少态,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門易遣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彼妻,“玉大人,你說我怎么就攤上這事豆茫∏惹福” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵揩魂,是天一觀的道長幽邓。 經(jīng)常有香客問我,道長火脉,這世上最難降的妖魔是什么牵舵? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮倦挂,結(jié)果婚禮上畸颅,老公的妹妹穿的比我還像新娘。我一直安慰自己方援,他們只是感情好没炒,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著犯戏,像睡著了一般送火。 火紅的嫁衣襯著肌膚如雪祖很。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天漾脂,我揣著相機與錄音假颇,去河邊找鬼。 笑死骨稿,一個胖子當著我的面吹牛笨鸡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播坦冠,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼形耗,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了辙浑?” 一聲冷哼從身側(cè)響起激涤,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎判呕,沒想到半個月后倦踢,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡侠草,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年辱挥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片边涕。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡晤碘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出功蜓,到底是詐尸還是另有隱情园爷,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布式撼,位于F島的核電站童社,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏端衰。R本人自食惡果不足惜叠洗,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望旅东。 院中可真熱鬧,春花似錦十艾、人聲如沸抵代。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽荤牍。三九已至案腺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間康吵,已是汗流浹背劈榨。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留晦嵌,地道東北人同辣。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像惭载,于是被迫代替她去往敵國和親旱函。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353