vue-cli的项目结构

2018-05-17 admin

前言

这篇文章对纯新手友好,所以有过任何vue开发经验的人可以出门左转啦!这篇文章献给我的homie苏蕾儿童鞋,让她在学习vue项目的时候少走一点弯路(径直冲向末路哈哈哈)。

本文将会简单的介绍一下vue的生态环境以及其中涉及的思想。如果刚从原始的HTML+JS+CSS中转型,这篇文章可能会比较适合你。 我也是最近刚刚上手vue,之前有过一丢丢react开发经验,所以对于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创建项目的教程网上很多,这里就不详细解释了,可以看到新建完成后项目目录如下图所示:

clipboard.png

在这个基础上我会再额外的新建两个文件夹views,apistore,这篇文章暂时用不到apistore,之后引入vuex之后会使用。 现在整体的项目目录如下:

clipboard.png

现在着重解释一下其中几个目录和文件分别用来干啥。

先看根目录下的文件。

package.json用来配置node环境,它会记录项目的相关信息以及该项目的依赖,有点像java的maven配置管理工具。通俗的来说,我们一个项目可能会用到很多外部依赖比如jquery。于是我们就需要一种科学有效的方式管理所有依赖及其对应的版本。而所有依赖都位于node_modules文件夹中。后面我们使用npm工具进行依赖管理时还会提到他。

.gitignore文件记录了git提交时不上传的内容,如node_modules中的全部内容。

index.html文件是项目的skeleton,我们来看一下它的内容:

<!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>

原文链接:https://segmentfault.com/a/1190000014892717

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-32391.html

文章标题:vue-cli的项目结构

相关文章
vue+element-ui+slot-scope实现可编辑表格
1.咱开发拿到需求大多数是去网上找成型的组件,找不到再看原生的方法能否实现,大牛除外哈,大牛一般喜欢封装组件框架。 2.可编辑表格在后台管理系统还是比较常用的,因为比较流行框架element,iview都没有这个应用,所以考虑了两种方法,下...
2017-12-25
从2014年的发展来展望JS的未来将会如何
&lt;font face=&quot;寰�杞�闆呴粦, Arial, sans-serif &quot;&gt;2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
12个你未必知道的CSS小知识
虽然CSS并不是一种很复杂的技术,但就算你是一个使用CSS多年的高手,仍然会有很多CSS用法/属性/属性值你从来没使用过,甚至从来没听说过。 1.CSS的color属性并非只能用于文本显示 对于CSS的color属性,相信所有Web开发人员...
2015-11-12
Vue获取DOM元素样式和样式更改示例
在 vue 中用 document 获取 dom 节点进行节点样式更改的时候有可能会出现 ‘style’ is not definde的错误,这时候可以在 mounted 里用 $refs 来获取样式,并进行更改: &lt;template...
2017-03-13
Vue.js组件tab实现选项卡切换
本文实例为大家分享了vue插件tab选项卡的具体代码,供大家参考,具体内容如下 效果图: 代码如下: &lt;!DOCTYPE html&gt; &lt;html lang=&quot;en&quot;&gt; &lt;head&gt; ...
2017-03-13
ajax为什么令人惊异?ajax的优缺点
使用Ajax的最大优点,就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。 Ajax不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。就像DHT...
2015-11-12
HTML5的5个不错的开发工具推荐
HTML5规范终于在今年正式定稿,对于从事多年HTML5开发的人员来说绝对是一个重大新闻。数字天堂董事长,DCloud CEO王安也发表了文章,从开发者和用户两个角度分析了HTML对两个人群的优势。其实,关于HTML5的开发工具,我们以往的...
2015-11-12
JavaScript教程:JS中的原型
Keith Peters 几年前发表的一篇博文,关于学习没有“new”的世界,其中解释了使用原型继承代替构造函数。两者都是纯粹的原型编码。 标准方法(The Standard Way) 一直以来,我们学习的在 JavaScript 里创建对...
2015-11-12
AJAX的浏览器支持
AJAX 的要点是 XMLHttpRequest 对象。 不同的浏览器创建 XMLHttpRequest 对象的方法是有差异的。 IE 浏览器使用 ActiveXObject,而其他的浏览器使用名为 XMLHttpRequest 的 Jav...
2015-11-12
Riot.js:不足1KB的MVP客户端框架
Riot.js是一款MVP(模型-视图-呈现)开源客户端框架,其最大的特点就是体积非常小,不足1KB,虽然体积小,但它可以帮助用户构建大规模的Web应用程序。 Riot.js是由Moot公司开发,目前最新版本为v0.9.2,遵循MIT开源许...
2016-03-11
回到顶部