天天看點

Vue項目 - 單檔案元件和Vue中的路由

推薦:​​Vue彙總​​

Vue項目 - 單檔案元件和Vue中的路由

什麼是單檔案元件

在之前的部落格中,部落客使用​

​Vue.component​

​​來定義全局元件,緊接着用​

​new Vue({ el: '#container '})​

​在每個頁面内指定一個挂載點。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <title>元件</title>
  <script src="./js/vue.js"></script>
</head>
<body>
<div id="div">
  <component v-bind:is="currentComponent">kaven</component>
  <button @click="click">切換</button>
</div>
</body>
</html>
<script>

  Vue.component("slot-welcome" , {
    template: `
           <div>
              <p>welcome </p>
              <slot></slot>
           </div>
        `
  });

  Vue.component("slot-hello" , {
    template: `
           <div>
              <p>hello </p>
              <slot></slot>
           </div>
        `
  });

  var vue = new Vue({
    el: '#div',
    data: {
      currentComponent: 'slot-hello'
    },
    methods: {
      click(){
        if(this.currentComponent === 'slot-hello'){
          this.currentComponent = 'slot-welcome'
        }
        else{
          this.currentComponent = 'slot-hello'
        }
      }
    }
  })
</script>      

這種方式在很多中小規模的項目中運作的很好,在這些項目裡JavaScript隻被用來加強特定的視圖。但當在更複雜的項目中,或者你的前端完全由JavaScript驅動的時候,下面這些缺點将變得非常明顯:

  1. 全局定義 ​

    ​(Global definitions)​

    ​​ :強制要求每個​

    ​component​

    ​中的命名不得重複。
  2. 字元串模闆 ​

    ​(String templates)​

    ​​ :缺乏文法高亮,在HTML有多行的時候,需要用到醜陋的​

    ​\​

    ​。
  3. 不支援 CSS ​

    ​(No CSS support)​

    ​ :意味着當HTML和JavaScript元件化時,CSS明顯被遺漏。
  4. 沒有建構步驟 ​

    ​(No build step)​

    ​​ :限制隻能使用HTML和ES5 JavaScript,而不能使用預處理器,如​

    ​Pug (formerly Jade)​

    ​​和​

    ​Babel​

    ​。

檔案擴充名為 ​

​.vue​

​​的​

​single-file components​

​​ (單檔案元件) 為以上所有問題提供了解決方法,并且還可以使用​

​webpack​

​​或​

​Browserify​

​等建構工具。

上一篇部落格介紹了Vue項目的檔案組成部分:​​Vue項目 - 項目檔案介紹​​。

其中就有根元件​

​App.vue​

​:

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>      

還有放置自定義元件的包​

​components​

​​中的​

​HelloWorld.vue​

​:

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li>
        <a
          href="https://vuejs.org"
          target="_blank"
        >
          Core Docs
        </a>
      </li>
      <li>
        <a
          href="https://forum.vuejs.org"
          target="_blank"
        >
          Forum
        </a>
      </li>
      <li>
        <a
          href="https://chat.vuejs.org"
          target="_blank"
        >
          Community Chat
        </a>
      </li>
      <li>
        <a
          href="https://twitter.com/vuejs"
          target="_blank"
        >
          Twitter
        </a>
      </li>
      <br>
      <li>
        <a
          href="http://vuejs-templates.github.io/webpack/"
          target="_blank"
        >
          Docs for This Template
        </a>
      </li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li>
        <a
          href="http://router.vuejs.org/"
          target="_blank"
        >
          vue-router
        </a>
      </li>
      <li>
        <a
          href="http://vuex.vuejs.org/"
          target="_blank"
        >
          vuex
        </a>
      </li>
      <li>
        <a
          href="http://vue-loader.vuejs.org/"
          target="_blank"
        >
          vue-loader
        </a>
      </li>
      <li>
        <a
          href="https://github.com/vuejs/awesome-vue"
          target="_blank"
        >
          awesome-vue
        </a>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>      

這些都是單檔案元件。

Vue項目 - 單檔案元件和Vue中的路由

現在,大家應該都知道什麼是單檔案元件了,其實就是在單個檔案中定義一個元件,這樣對于元件的複用、修改都很友善;一個重要的事情值得注意,關注點分離不等于檔案類型分離。在現代UI開發中,我們已經發現相比于把代碼庫分離成三個大的層次(HTML、CSS、Javascript)并将其互相交織起來,把它們劃分為松散耦合的元件再将其組合起來更合理一些。在一個元件裡,其模闆、邏輯和樣式是内部耦合的,并且把它們搭配在一起實際上使得元件更加内聚且更可維護。建立一個Vue項目後,當運作這個Vue項目時,基本上都會出現如下圖所示頁面。

Vue項目 - 單檔案元件和Vue中的路由

那麼為什麼運作Vue項目,首頁是上圖所示頁面呢?這就要涉及到Vue中的路由了。

首頁​

​index.html​

​:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>project</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>      

很明顯首頁中​

​id="app"​

​​的​

​div​

​​标簽被入口檔案​

​main.js​

​中定義的元件挂載了。

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})      

而入口檔案​

​main.js​

​​中定義的元件使用了根元件(App),并且定義模闆​

​template​

​​為​

​<App/>​

​​,是以​

​<div id="app"></div>​

​​就相當于​

​<App/>​

​​;并且入口檔案​

​main.js​

​​中還引入了​

​router​

​​,當引入​

​router​

​​後,Vue項目會自動加載檔案夾​

​router​

​​下的檔案​

​index.js​

​​,該檔案定義了路由規則。ES6文法,當鍵和值相同時,如​

​router: router​

​​、​

​App: App​

​​就可以寫成​

​router​

​​、​

​App​

​。

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})      

可以知道當路徑為​

​'/'​

​​時,使用路由後,會被路由到​

​HelloWorld​

​元件。

而路由是在哪裡觸發的呢?其實是根元件中的​

​<router-view/>​

​​标簽,是以這部分區域路由到了​

​HelloWorld​

​元件。

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>      

是以​

​<img src="./assets/logo.png">​

​對應于Vue的圖檔。

Vue項目 - 單檔案元件和Vue中的路由

而​

​<router-view/>​

​​标簽會路由到​

​HelloWorld​

​元件,對應于下面的文字和連結。

Vue項目 - 單檔案元件和Vue中的路由

繼續閱讀