ECMAScript【Vue 入门】使用 Vue2 开发一个示类型列表的行使

前言

直白无找到一个合适的示个人项目之模版,所以自己动手使用 Vue
写了一个。该模板基于 Markdown 文件进行布置,只待以一定规则编写
Markdown 文件,然后下一个
在线工具 转为 JSON
文件即可。下面是拖欠种之在线地址与源码。本文主要记录转路遭到因故到的相关知识。

在线演示   
源码

效果

次第最终的意义使下图所示:

ECMAScript 1

全项目就含有两单零件:项目介绍 和
侧边导航,逻辑比较简单,十分顺应入门。

条件布置

此地我们以 Gulp 和 Webpack 用作项目构建工具。初次使用 Gulp 和 Webpack
可能不顶适应,因为她的布局或者为你看之一头雾水。不过并非担心,这点儿单究竟只是是一个家伙,在上马时尚未必要专门之打听它的行事规律,只要能够运作起来就是可以。等及下了一段时间之后,自然而然的就是懂得该如何安排了。这里要记录转档次蒙行使的布局,如果想如果系统的读怎么样使用即时点儿个器,可以参考下面的章:

  • Gulp入门教程
  • 一律钟头包教会 —— webpack
    入门指南

Gulp 和 Webpack 集成

Gulp 和 Webpack 集成一个比较简单的措施就是将 Webpack 作为 Gulp 的一个
task,如下面的款型:

var gulp = require("gulp");
var webpack = require("webpack");

gulp.task("webpack", function (callback) {
    //webpack配置文件
    var config = {
        watch: true,
        entry: {
            index: __dirname + '/src/js/index.js'
        },
        output: {
            path: __dirname + '/dist/js',
            filename: '[name].js'
        }
        //........
    };
    webpack(config, function (err, stats) {
        console.log(stats.toString());
    });
});

gulp.task('default', [ 'webpack']);

下我们独家介绍一下 gulp 和 webpack 的配备

Gulp 配置

Gulp 中最主要安排了少单任务:webpack 和 browserSync,这里要说一下
browserSync。browserSync
主要用于自动刷新浏览器。首先我们配备需要监听的文书,当这些文件发出变动后,调用
browserSync 使浏览器自动刷新页面。下面是具体的配备

var gulp = require("gulp");
var browserSync = require('browser-sync');

// 添加 browserSync 任务
gulp.task('browserSync', function () {
    browserSync({
        server: {
            baseDir: '.'
        },
        port: 80
    })
});

// 配置需要监听的文件,当这些文件发生变化之后
// 将调用 browserSync.reload 使浏览器自动刷新
gulp.task("watch", function () {
    gulp.watch("./**/*.html", browserSync.reload);
    gulp.watch("dist/**/*.js", browserSync.reload);
    gulp.watch("dist/**/*.css", browserSync.reload);
});

// 添加到默认任务
gulp.task('default', ['browserSync', 'watch', 'webpack']);

Webpack 配置

咱俩运用 webpack
进行资源打包的行事,就是说将各种资源(css、js、图片等)交给 Webpack
进行管理,它见面拿资源整合压缩,我们以页面中只是需要引用压缩后的文书即可。webpack
的根底配置文件如下所示

gulp.task("webpack", function (callback) {

    //webpack配置文件
    var config = {
        // true 表示 监听文件的变化
        watch: true,
        // 加载的插件项
        plugins: [
            new ExtractTextPlugin("../css/[name].css")
        ],
        // 入口文件配置
        entry: {
            index: __dirname + '/src/js/index.js'
        },
        // 输出文件配置
        output: {
            path: __dirname + '/dist/js',
            filename: '[name].js'
        },

        module: {
            // 加载器配置,它告诉 Webpack 每一种文件需要采用什么加载器来处理,
            // 只有配置好了加载器才能处理相关的文件。
            // test 用来测试是什么文件,loader 表示对应的加载器
            loaders: [
                {test: /\.vue$/, loader: 'vue-loader'}
            ]
        },
        resolve: {
            // 模块别名定义,方便后续直接引用别名,无须多写长长的地址
            // 例如下面的示例,使用时只需要写 import Vue from "vue"
            alias: {
                vue: path.join(__dirname, "/node_modules/vue/dist/vue.min.js")
            },
            // 自动扩展文件后缀名,在引入文件时只需写文件名,而不用写后缀
            extensions: ['.js', '.json', '.less', '.vue']
        }
    };
    webpack(config, function (err, stats) {
        console.log(stats.toString());
    });
});

webpack 的相干配置说明可以参照前的给有的稿子,下面说一下施用 webpack 2
赶上的坑:

extract-text-webpack-plugin

extract-text-webpack-plugin 会将 css 样式打包改成一个独立的 css
文件,而休是一直拿样式打包到 js 文件中。下面是采用方法

{
    plugins: [new ExtractTextPlugin("../css/[name].css")],
    module: {
        loaders: [{
            test: /\.css$/,
            loader: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader"
            })
        },
        {
            test: /\.less$/,
            loader: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: "css-loader!less-loader"
            })
        }
    },
}

此地用专注的地方便是,extract-text-webpack-plugin 在 webpack 1 以及
webapck 2 中之设置方式不同,需要根据使用的 webpack 版本来安装:

# for webpack 1
npm install --save-dev extract-text-webpack-plugin
# for webpack 2
npm install --save-dev extract-text-webpack-plugin@beta

压缩文件

下 UglifyJsPlugin 插件可以减小 css 和 js
文件,但是同开始经常连连力不从心压缩文件,后来查阅了瞬间素材,大概是以下面几乎个因:

  1. uglifyjs-webpack-plugin 依赖让 uglify-js,而 uglify-js 默认不支持
    ES6 语法,所以要安装支撑 ES6 语法的 uglify-js
    npm install mishoo/UglifyJS2#harmony --save
  2. webpack 2 中,UglifyJsPlugin 默认不抽 loaders,如果要启动 loaders
    压缩,需要参加下面的布置:
    js plugins: [ new webpack.LoaderOptionsPlugin({ minimize: true }) ]

倘依上面的改动了要无可知压缩文件,可以尝试着用 node_modules
删除,然后重新安装依赖。

Vue

遵照有的重要记录转顺序中因故到的 Vue 语法,如果想只要系的求学一下
Vue.js,可以参照下面的章:

  • Vue.js 教程

HelloWorld

咱俩第一来拘禁一个无比简单易行的 Vue 示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue Demo</title>
</head>
<body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
    {{ message }}
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            message: 'Hello Vue!'
        }
    })
</script>

</body>
</html>

每个 Vue 应用还见面创造一个 Vue 的到底实例,在干净实例中要传入 html 标签的
id,用来告诉 Vue 该标签中之情节要让 Vue
来分析。上面是一个大概的数量绑定的示范,在运转实 {{ message }}
会被分析为 “Hello Vue!”。

基础

本节参考自 Vue 中文文档,略有修改

每当形容 Vue 应用之前,我们而熟悉一下 Vue
的主干语法,主要不外乎数据绑定、事件处理、条件、循环等,下面我们逐个看下系的知。

数绑定

Vue.js 使用了根据 HTML 的沙盘语法,允许开发者声明式地拿 DOM 绑定至底层
Vue 实例的数额。所有 Vue.js 的沙盘都是法定的 HTML
,所以能够为按规范之浏览器与 HTML 解析器解析。下面是 Vue.js
数据绑定的连带语法:

  • 文本
    数量绑定最广大的形式就是使用 “Muestache”
    语法(双大括声泪俱下),如下面的款型:

    Message: {{ msg }} 
    

    Muestache 标签会让分析为相应对象及之 msg 属性值。当 msg
    属性发生改变以后,Muestache 标签处解析的情呢会趁机更新。

    透过运用 v-once
    指令,我们得以实施一次性解析,即数据变动时,解析的情节不见面随着更新。需要专注的是
    v-once 会影响该节点上之有所数据绑定

    This will never change: {{ msg }}
    
  • Raw HTML
    凭属性值是啊内容,Muestache
    标签里的情还见面受解析为纯文本。如果希望用绑定的值解析为 HTML
    格式,就需采用 v-html 指令:

    <div v-html="variable"></div>
    
  • 属性值
    Mustache 语法不克因此在 HTML 的特性被,如果想也性绑定变量,需要以
    v-bind 指令:

    <div v-bind:id="dynamicId"></div>
    

    假设 dynamicId=1,那么地方代码就见面被解析为

    <div id="1"></div>
    

    另外 v-bind 指令可以于缩写为
    :,所以我们在先后中时常来看的凡底下的语法形式:

    <div :id="dynamicId"></div>
    <!-- 等价于 -->
    <div v-bind:id="dynamicId"></div>
    
  • 表达式
    对于持有的数绑定, Vue.js 都提供了一心的 JavaScript
    表达式支持,如下面的款型:

    // 加法
    {{ number + 1 }}
    
    // 三元表达式
    {{ ok ? 'YES' : 'NO' }}
    
    // JS 库函数
    {{ message.split('').reverse().join('') }}
    
    // 指令中使用表达式
    <div v-bind:id="'list-' + id"></div>
    

事件处理

通过动 v-on 指令可以监听 DOM 事件来点 JS
处理函数,下面是一个总体的以身作则:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue Demo</title>
</head>
<body>
<script src="https://unpkg.com/vue/dist/vue.js"></script>

<div id="app">
    <button v-on:click="increase">增加 1</button>
    <p>这个按钮被点击了 {{ counter }} 次。</p>
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            counter: 0
        },
        methods: {
            increase: function() {
                this.counter++;
            }
        }
    })
</script>

</body>
</html>

平常情况下,v-on 会被简写为 @,所以我们于程序中貌似是相下面的样式

<button @click="increase">增加 1</button>
<!-- 等价于 -->
<button v-on:click="increase">增加 1</button>

格令 v-if

经 v-if 指令我们好因一些原则来支配是否渲染内容,如下面的形式

<h1 v-if="ok">Yes</h1>

咱们司空见惯以 v-if 和 v-else 结合起来用,如下所示:

<div v-if="Math.random() > 0.5">
    Now you see me
</div>
<div v-else>
      Now you don't
</div>

在 Vue 2.1.0 中新增了一个 v-else-if 指令,可以拓展链式判断:

<div v-if="type === 'A'">
    A
</div>
<div v-else-if="type === 'B'">
      B
</div>
<div v-else-if="type === 'C'">
      C
</div>
<div v-else>
      Not A/B/C
</div>

循环指令 v-for

通过 v-for
指令,我们可以根据同样组数据进行迭代渲染,下面是一个为主示例:

<ul id="example-1">
    <li v-for="item in items">
        {{ item.message }}
    </li>
</ul>

var example1 = new Vue({
    el: '#example-1',
    data: {
        items: [
              {message: 'Foo' },
              {message: 'Bar' }
        ]
    }
})

地方是一个简练的对数组迭代的以身作则,我们还好对对象开展迭代,如果只使用一个参数,就是对准对象的属于性值进行迭代:

<ul id="repeat-object" class="demo">
    <li v-for="value in object">
        {{ value }}
    </li>
</ul>

假定传入第二只参数,就是对准对象的属性值以及性能名展开迭代,注意这里二独参数表示的是属性名,也就算是
key

<div v-for="(value, key) in object">
    {{ key }} : {{ value }}
</div>

如再次盛传第三独参数,第三个参数就表示索引

<div v-for="(value, key, index) in object">
  {{ index }}. {{ key }} : {{ value }}
</div>

组件

零件是 Vue.js 最劲的作用之一。组件可以扩大
HTML元素,封装可选用的代码。在我们的先后中蕴藏两只零部件:project 组件和
sidebar 组件,如下图所出示。这里我们最主要介绍单文件组件的采用,即将组件用到
html、js 和 css 都勾于一个文本里,每个组件自成一个系。

ECMAScript 2

文件结构

单文件组件一般使用 “.vue” 作为后缀名,一般的文书结构如下所示:

project.vue

<template>
    <div>
        {{ key }}
    </div>
</template>

<script>
    export default {
        data: function() {
            return {
                "key": "value"
            }
        },

        methods:  {
            demoMethod: function() {

            }
        }

    }
</script>

<style lang="less">
    @import "xxx.less";
</style>

export 将模块输出,default
表明以文件称当模块输出名,这就是仿佛于用模块于网被登记一下,然后另外模块才可用使用
import 引用该模块。

然后我们需要在主文件中注册该零件:

index.js

import project from '../components/project/project.vue'
Vue.component("project", project);

当注册就以后,就足以 html 中利用该零件了

index.html

<project></project>

生命周期

Vue 的而让组件会经历 创建 -> 编译 -> 挂载 -> 卸载 -> 销毁
等一样雨后春笋事件,这些事件闹的光景都见面触发一个息息相关的钩子(hook)函数,通过这些钩子函数,我们得以事变产生的光景举行一些操作,下面先押下官方给起底一个
Vue 对象的生命周期图,其中红框内标注的尽管是相应的钩函数

ECMAScript 3

下是关于这些钩子函数的分解:

hook 描述
beforeCreate 组件实例刚被创建,组件属性计算之前
created 组件实例创建完成,属性已绑定,但是 DOM 还未生成, $el 属性还不存在
beforeMount 模板编译/挂载之前
mounted 模板编译/挂载之后
mounted 模板编译/挂载之后(不保证组件已在 document 中)
beforeUpdate 组件更新之前
updated 组件更新之后
activated for keep-alive,组件被激活时调用
deactivated for keep-alive,组件被移除时调用
beforeDestory 组件销毁前调用
destoryed 组件销毁后调用

下是钩子函数的动办法:

export default {
    created: function() {
        console.log("component created");
    },
    data {},
    methods: {}
}

父子组件通信

父子组件通信可以使用 props down 和 events up 来讲述,父组件通过 props
向下传递数据给子组件,子组件通过 events 给父亲组件发送信息,下面示意图:

ECMAScript 4

图片来自 https://github.com/webplus/blog/issues/10

父亲组件向子组件传递数据

由此行使
props,父组件可以拿数据传递给子组件,这种传递是仅仅为的,当爹组件的特性发生变化时,会传送给子组件,但是非见面倒过来。下面是一个演示

comp.vue

<template>
    {{ message }}{{ shortMsg }}
</template>

<script>
    export default {
        props: ["message", "shortMsg"],

    }
</script>

index.html

<div id="app">
    <!-- 在这里将信息传递给子组件,:message 表示子组件中的变量名 -->
    <comp :message="hello" :short-msg = "hi"></comp>
</div>

<script>
    var app = new Vue({
        el: '#app',
        data: {
            "hello": "Hello",
            "hi": "Hi"
        }

    })
</script>

在方的流程中,父组件首先将传递的数码绑定到子组件的性质上,然后子组件在
props
中声称和绑定属性相同之变量名,就得运用该变量了,需要留意的一点凡是如变量采用驼峰的命名方式,在绑定属性时,就要用驼峰格式改呢
- 连接的款型,如果点所示 shortMsg -> short-msg

子组件为大组件通信

如果子组件需要把消息传送让父亲组件,可以运用自定义事件:

  1. 利用 $on(eventName) 监听事件
  2. 运用 $emit(eventName) 触发事件

下是一个示范:

comp.vue

<script>
    export default {
        methods: {
            noticeParent: function() {
                // 事件名,传输值
                this.$emit('child_change', "value");
            }
        }
    }
</script>

index.html

<div id="app">
    <comp @child_change="childChange"></comp>
</div>
<script>
    var app = new Vue({
        el: '#app',
        methods: {
            childChange: function(msg) {
                console.log("child change", msg);
            }
        }
    });
</script>

于点的代码中,父组件通过 v-on 绑定了 child_chagne 事件,当
child_chagne 事件于触发时就会调用 childChange
方法。在分组件中得以经过 $emit 触发 child_change
事件。这里需要小心的是事件名不用采用驼峰命名,也毫不用 -
字符,可以下下划线 _ 连接单词。

Event Bus 通信

Event Bus
通信模式是一模一样种更加通用的通信方式,它既是好用来父子组件为足以用于非父子组件。它的法则就是是使用一个缺损的
Vue
实例作为中央事件总线,通过自定义事件的监听与沾,来形成通信功能,下面是一个示意图:

ECMAScript 5

图形来自 https://github.com/webplus/blog/issues/10

下面我们来拘禁一个切实的实例:

  • 率先定义一个拖欠的 Vue 实例,作为事件总线

    EventBus.js

    import Vue from 'vue'
    export default new Vue()
    
  • 以组件一中针对某事件进展监听

    comp1.vue

    <script>
    import eventBus from "EventBus.js"
    export default {
        created: function() {
            eventBus.$on("change", function() {
                console.log("change");
            })
        }
    }
    </script>
    
  • 在组件二着触发相应事件形成通信

    comp2.vue

    <script>
    import eventBus from "EventBus.js"
    export default {  
        methods: {
            notice: function() {
                this.$emit('change', "value");
            }
        }
    }
    </script>
    

ES6

本节增选自 ECMAScript 6 入门

跟 ES5 相比,ES6 提供了更进一步完美的功效以及语法,程序中我们以部分 ES6
语法,这里召开一个简短的记录,如果想只要系的求学 ES6,可以参照下面的章:

  • ECMAScript 6 入门

let

ES6 新增了 let 命令,用于声明变量。使用 let
声明的变量具有块级作用域,所以在声明变量时,应该运用 let,而不是 var。

{
  let a = 10;
  var b = 1;
}

a // ReferenceError: a is not defined.
b // 1

for of 循环

ES6 借鉴 C++、Java、C# 和 Python
语言,引入了for…of循环,作为遍历所有数据结构的合之主意

const arr = ['red', 'green', 'blue'];

for(let v of arr) {
  console.log(v); // red green blue
}

Set 和 Map

ES6 引入了 Set 和 Map 结构。下面是双边的切实介绍

Set

属性

属性 描述
Set.prototype.size 返回Set实例的成员总数。

方法

方法名 描述
add(value) 添加某个值,返回Set结构本身。
delete(value) 删除某个值,返回一个布尔值,表示删除是否成功。
has(value) 返回一个布尔值,表示该值是否为Set的成员。
clear() 清除所有成员,没有返回值。
   
keys() 返回键名的遍历器
values() 返回键值的遍历器
entries() 返回键值对的遍历器
forEach() 使用回调函数遍历每个成员

使示例:

const s = new Set();

[2, 3, 5, 4, 5, 2, 2].forEach(x => s.add(x));

for (let i of s) {
  console.log(i);
}

Map

属性

属性 描述
Map.prototype.size 返回 Map 实例的成员总数。

方法

方法名 描述
set(key, value) set方法设置键名key对应的键值为value,然后返回整个 Map 结构。如果key已经有值,则键值会被更新,否则就新生成该键。
get(key) 读取 key 对应的键值,如果找不到 key,返回 undefined。
has(key) 返回一个布尔值,表示某个键是否在当前 Map 对象之中。
delete(key) 删除某个键,返回true。如果删除失败,返回false。
clear() 清除所有成员,没有返回值。
   
keys() 返回键名的遍历器
values() 返回键值的遍历器
entries() 返回所有成员的遍历器
forEach() 遍历 Map 的所有成员。

使示例:

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
m.get(o) // "content"

m.has(o) // true
m.delete(o) // true
m.has(o) // false

参考文章

  • Vue 2.0
    升(cai)级(keng)之旅
  • Vue
    2.0开销执行(组件间通讯)
  • Vuejs2.0
    组件通讯总结