vue-cli的項目結構

前言

這篇文章對純新手友好,因此有過任何vue開發經驗的人能夠出門左轉啦!這篇文章獻給個人homie蘇蕾兒童鞋,讓她在學習vue項目的時候少走一點彎路(徑直衝向末路哈哈哈)。javascript

本文將會簡單的介紹一下vue的生態環境以及其中涉及的思想。若是剛從原始的HTML+JS+CSS中轉型,這篇文章可能會比較適合你。
我也是最近剛剛上手vue,以前有過一丟丟react開發經驗,因此對於vue的總體思路有些許的瞭解。粗鄙之見也請各位大佬多多指教。html

本文將會涉及以下內容:vue

  • vue
  • vue,vuex和vue-router的關係
  • 爲什麼須要vuex和vue-router
  • vue-cli建立項目以及項目結構講解
  • 以官方提供的todolist做爲初始項目講解vue的基本語法,後面會陸續加入vuex和vue-router的使用

Vue

Vue語言有很是強的靈活性,能夠直接在HTML頁面中經過引入其js文件使用,也能夠做爲一個完整的項目使用。一般狀況下,咱們會將其做爲一個完整的項目使用。這裏我使用vue-cli新建一個基於webpack的vue項目。vue-cli建立項目的教程網上不少,這裏就不詳細解釋了,能夠看到新建完成後項目目錄以下圖所示:java

clipboard.png

在這個基礎上我會再額外的新建兩個文件夾views,apistore,這篇文章暫時用不到apistore,以後引入vuex以後會使用。
如今總體的項目目錄以下:node

clipboard.png

如今着重解釋一下其中幾個目錄和文件分別用來幹啥。react

先看根目錄下的文件。jquery

package.json用來配置node環境,它會記錄項目的相關信息以及該項目的依賴,有點像java的maven配置管理工具。通俗的來講,咱們一個項目可能會用到不少外部依賴好比jquery。因而咱們就須要一種科學有效的方式管理全部依賴及其對應的版本。而全部依賴都位於node_modules文件夾中。後面咱們使用npm工具進行依賴管理時還會提到他。webpack

.gitignore文件記錄了git提交時不上傳的內容,如node_modules中的所有內容。git

index.html文件是項目的skeleton,咱們來看一下它的內容:github

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

這裏除了將網頁標題命名爲咱們的項目標題以外,還有一個id爲app的div。全部的頁面將以index.html做爲大框架,將元素插入到div中。後面還會繼續說起。

build,config文件夾涉及了各類配置文件,這裏不贅述,由於我也不是很會webpack哈哈哈。

項目的核心代碼都位於src文件夾之下,在這個文件夾下,咱們看到一個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>

它構建了一個名爲App的模塊。其實,這是整個項目的入口模塊,全部的渲染都將會通過App模塊,而後渲染至<div id="app"></div>。所以能夠在App.vue文件中定義整個項目最通用的結構好比Header,Sidebar等等。其它狀況下也能夠不對其進行任何修改。

components文件夾和views文件夾都用來存儲模板,不一樣的是views文件夾中的內容對應一個完整的頁面,而components中的內容對應各個可重用的元素。好比views對應一個用戶我的信息界面,而components中可能包好這個界面中的Header,Sidebar,核心用戶信息模塊等等。

assets中包含靜態信息如圖片等

router目錄之下index.js對應了vue-router的配置,涉及vue-router時會繼續說起。

至此咱們基本瞭解了vue項目中各個文件夾的做用。那麼如何啓動這個項目呢?這就須要咱們的npm指令。

npm

npm的指令不少,核心的咱們暫時只須要了解一下兩種就能夠了:
npm install: 安裝依賴,好比咱們須要安裝jquery,就可使用npm install jquery。在不指定版本號的狀況下會下載最新版本
npm run dev: 運行開發配置下的項目,咱們用這個指令在開發過程當中啓動項目並debug

進入代碼

該todo來自於vue官網上,須要查看源碼的能夠去官網的github上下載。
首先咱們須要使用npm install來安裝項目現有的依賴,項目現有的依賴會從package.json文件夾中查看並下載。依賴下載的過程會比較慢,可使用淘寶開發的cnpm。

咱們在使用npm run dev查看一下運行結果:

clipboard.png

主要的組件都位於components之下:

clipboard.png
分別對應着新建Todo模塊,單個Todo展現頁面和Todo列表模塊。由於這是一個單頁面app,全部沒有用到views來組裝,而是直接在App.vue中進行組裝。

<template>
  <div id="app">
    <h1 class="ui dividing centered header">Vue.js Todo App</h1>
    <div class='ui three column centered grid'>
      <div class='column'>
        <todo-list v-bind:todos="todos"></todo-list>
        <create-todo v-on:create-todo="createTodo"></create-todo>
      </div>
    </div>
  </div>
</template>

<script>
import sweetalert from 'sweetalert';
import TodoList from './components/TodoList';
import CreateTodo from './components/CreateTodo';

export default {
  name: 'app',
  components: {
    TodoList,
    CreateTodo,
  },
  data() {
    return {
      todos: [{
        title: 'Todo A',
        project: 'Project A',
        done: false,
      }, {
        title: 'Todo B',
        project: 'Project B',
        done: true,
      }, {
        title: 'Todo C',
        project: 'Project C',
        done: false,
      }, {
        title: 'Todo D',
        project: 'Project D',
        done: false,
      }],
    };
  },
  methods: {
    createTodo(newTodo) {
      this.todos.push(newTodo);
      sweetalert('Success!', 'To-Do created!', 'success');
    },
  },
};
</script>

這裏引入了TodoList和CreateTodo模板,並在<template>中使用。同時還用props傳入了一組todo的數組模擬現有的todo內容。具體的vue語法這裏將不涉及,能夠去官網上學習,官網的教程能夠說是很是新手友好了呢。

而後咱們來看一看TodoList.vue

<template>
  <div>
    <p class="tasks">Completed Tasks: {{todos.filter(todo => {return todo.done === true}).length}}</p>
    <p class="tasks">Pending Tasks: {{todos.filter(todo => {return todo.done === false}).length}}</p>
    <todo v-on:delete-todo="deleteTodo" v-on:complete-todo="completeTodo" v-for="todo in todos" :todo.sync="todo"></todo>
  </div>
</template>

<script type = "text/javascript" >
import sweetalert from 'sweetalert';
import Todo from './Todo';

export default {
  props: ['todos'],
  components: {
    Todo,
  },
  methods: {
    deleteTodo(todo) {
      sweetalert({
        title: 'Are you sure?',
        text: 'This To-Do will be permanently deleted!',
        type: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#DD6B55',
        confirmButtonText: 'Yes, delete it!',
        closeOnConfirm: false,
      },
      () => {
        const todoIndex = this.todos.indexOf(todo);
        this.todos.splice(todoIndex, 1);
        sweetalert('Deleted!', 'Your To-Do has been deleted.', 'success');
      });
    },
    completeTodo(todo) {
      const todoIndex = this.todos.indexOf(todo);
      this.todos[todoIndex].done = true;
      sweetalert('Success!', 'To-Do completed!', 'success');
    },
  },
};
</script>

<style scoped>
p.tasks {
  text-align: center;
}
</style>

如今看Todo.vue文件。

<template>
  <div class='ui centered card'>
    <div class="content" v-show="!isEditing">
      <div class='header'>
          {{ todo.title }}
      </div>
      <div class='meta'>
          {{ todo.project }}
      </div>
      <div class='extra content'>
          <span class='right floated edit icon' v-on:click="showForm">
          <i class='edit icon'></i>
        </span>
        <span class='right floated trash icon' v-on:click="deleteTodo(todo)">
          <i class='trash icon'></i>
        </span>
      </div>
    </div>
    <div class="content" v-show="isEditing">
      <div class='ui form'>
        <div class='field'>
          <label>Title</label>
          <input type='text' v-model="todo.title" >
        </div>
        <div class='field'>
          <label>Project</label>
          <input type='text' v-model="todo.project" >
        </div>
        <div class='ui two button attached buttons'>
          <button class='ui basic blue button' v-on:click="hideForm">
            Close X
          </button>
        </div>
      </div>
    </div>
    <div class='ui bottom attached green basic button' v-show="!isEditing &&todo.done" disabled>
        Completed
    </div>
    <div class='ui bottom attached red basic button' v-on:click="completeTodo(todo)" v-show="!isEditing && !todo.done">
        Pending
    </div>
  </div>
</template>

<script type="text/javascript">
  export default {
    props: ['todo'],
    data() {
      return {
        isEditing: false,
      };
    },
    methods: {
      completeTodo(todo) {
        this.$emit('complete-todo', todo);
      },
      deleteTodo(todo) {
        this.$emit('delete-todo', todo);
      },
      showForm() {
        this.isEditing = true;
      },
      hideForm() {
        this.isEditing = false;
      },
    },
  };
</script>

它的<template>中包含了一個Todo塊的信息。以後TargetList.vue用它來展現所有的Todo。

<template>
  <div>
    <p class="tasks">Completed Tasks: {{todos.filter(todo => {return todo.done === true}).length}}</p>
    <p class="tasks">Pending Tasks: {{todos.filter(todo => {return todo.done === false}).length}}</p>
    <todo v-on:delete-todo="deleteTodo" v-on:complete-todo="completeTodo" v-for="todo in todos" :todo.sync="todo"></todo>
  </div>
</template>

<script type = "text/javascript" >
import sweetalert from 'sweetalert';
import Todo from './Todo';

export default {
  props: ['todos'],
  components: {
    Todo,
  },
  methods: {
    deleteTodo(todo) {
      sweetalert({
        title: 'Are you sure?',
        text: 'This To-Do will be permanently deleted!',
        type: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#DD6B55',
        confirmButtonText: 'Yes, delete it!',
        closeOnConfirm: false,
      },
      () => {
        const todoIndex = this.todos.indexOf(todo);
        this.todos.splice(todoIndex, 1);
        sweetalert('Deleted!', 'Your To-Do has been deleted.', 'success');
      });
    },
    completeTodo(todo) {
      const todoIndex = this.todos.indexOf(todo);
      this.todos[todoIndex].done = true;
      sweetalert('Success!', 'To-Do completed!', 'success');
    },
  },
};
</script>

<style scoped>
p.tasks {
  text-align: center;
}
</style>
相關文章
相關標籤/搜索