【Vue 入门】使用 Vue2 开发一个展示项目列表的应用

前言

一直没有找到一个合适的展示个人项目的模板,所以自己动手使用 Vue 写了一个。该模板基于 Markdown 文件进行配置,只需要按一定规则编写 Markdown 文件,然后使用一个 在线工具 转为 JSON 文件即可。下面是该项目的在线地址和源码。本文主要记录一下项目中用到的相关知识。

在线演示    源码

效果

程序最终的效果如下图所示:

整个项目只包含两个组件:项目介绍 和 侧边导航,逻辑比较简单,十分适合入门。

环境配置

这里我们使用 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,可以参考下面的文章:

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” 语法(双大括号),如下面的形式:

    <span>Message: {{ msg }} </span>

    Muestache 标签会被解析为对应对象上的 msg 属性值。当 msg 属性发生改变之后,Muestache 标签处解析的内容也会随着更新。

    通过使用 v-once 指令,我们可以执行一次性解析,即数据改变时,解析的内容不会随着更新。需要注意的是 v-once 会影响该节点上的所有数据绑定

    <span v-once>This will never change: {{ msg }}</span>
  • Raw HTML

    不论属性值是什么内容,Muestache 标签里的内容都会被解析为纯文本。如果希望将绑定的值解析为 HTML 格式,就需要使用 v-html 指令:

    html

    <div v-html="variable"></div>

  • 属性值

    Mustache 语法不能用在 HTML 的属性中,如果想为属性绑定变量,需要使用 v-bind 指令:

    html

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

    假设 dynamicId=1,那么上面代码就会被解析为

    html

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

    另外 v-bind 指令可以被缩写为 :,所以我们在程序中经常看到的是下面的语法形式:

    html

    <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 都写在一个文件里,每个组件自成一个系统。

文件结构

单文件组件一般使用 “.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 对象的生命周期图,其中红框内标出的就是对应的钩子函数

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

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 给父组件发送消息,下面示意图:

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

父组件向子组件传递数据

通过使用 props,父组件可以把数据传递给子组件,这种传递是单向的,当父组件的属性发生变化时,会传递给子组件,但是不会反过来。下面是一个示例

comp.vue

<template>
    <span>{{ message }}{{ shortMsg }}</span>
</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 实例作为中央事件总线,通过自定义事件的监听和触发,来完成通信功能,下面是一个示意图:

图片来自 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,可以参考下面的文章:

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

参考文章

时间: 2024-08-18 20:18:16

【Vue 入门】使用 Vue2 开发一个展示项目列表的应用的相关文章

【转载】【Vue 入门】使用 Vue2 开发一个展示项目列表的应用

目录 前言 效果 环境配置 Gulp 和 Webpack 集成 Gulp 配置 Webpack 配置 Vue HelloWorld 基础 组件 ES6 let for of 循环 Set 和 Map 参考文章 前言 一直没有找到一个合适的展示个人项目的模板,所以自己动手使用 Vue 写了一个.该模板基于 Markdown 文件进行配置,只需要按一定规则编写 Markdown 文件,然后使用一个 在线工具 转为 JSON 文件即可.下面是该项目的在线地址和源码.本文主要记录一下项目中用到的相关知识

一,入门基础—— 2. 第一个project项目

1. 欢迎界面的右边是一个项目列表,显示全部近期打开的项目,双击??打开之前创建的项目. 2.右击??处,选择"Add Files to DemoApp..."加入一张图片. 3. 选中一张图片,确保选中了"Copy item if need...",点击add加入图片. 4. 选择"viewController.m"文件,在编辑框中加入以上代码,然后点击执行button. 5. 成功显示图片 一,入门基础-- 2. 第一个project项目,布

开发一个app项目需要多少钱?

开发一个app项目需要多少钱? .客户经常问“开发一个APP需要多少钱?”“做个app需要多少预算?”“开发个APP的价钱?”等等有关app开发价格方面.为此上海储君科技公司针对这一系列的问题做个整理: 现在的市面上有两种APP开发模式,一种是模板APP,一种是定制型开发的APP,两个分类价格也千差万别. 第一种,模板APP,它的市场价格几千到几万不等,相比APP定制开发价格是相当便宜的.但是也存在着一定的缺点.APP模板的源代码版权是APP 开发公司所有的,而且企业用户每年需要 交付一定的管理

Python开发入门与实战2-第一个Django项目

2.第一个Django项目 上一章节我们完成了python,django和数据库等运行环境的安装,现在我们来创建第一个django project吧,迈出使用django开发应用的第一步. 2.1.创建第一个Django项目 我们创建一个我们存放Django的工作目录,示例:C:\My Files\Python Projects 在命令提示符窗口进入到刚才创建的目录,运行运行命令: django-admin.py startproject mysite 这样会在你的当前目录下创建一个目录mysi

vue.js使用vue-cli搭建一个SPA项目

WHY 之所以写这篇如何运用脚手架自动化构建出一个项目的大架构,主要是面向想入门vue的小伙伴.之前,我第一次接触vue,一直摸不着头脑,想在网上搜个接地气的教程都找不到.SO,我以如何搭建结构为开始,向想入门vue的童鞋们把我仅有的力量贡献出来,随后我会持续更新vue如何与ui框架结合使用:在低版本ie如何运用vwjs将其打包为桌面应用以及我在实际开发的过程中踩过的各种坑.欢迎大家观看与互相交流哦. HOW 话不多说,切入主题 1.首先,你的电脑需要nodejs环境,如果没有,点击下面链接去下

swing开发一个修改项目数据库连接参数配置文件

我们在开发web项目中,经常有properties配置文件配置数据库连接参数,每次修改的时候还要去找到配置文件,感觉有点麻烦,就用swing做了个小工具修改参数,运行界面如下: ============================================================== 一.项目结构: 二.相关代码: 1.ConfigTools.java package com.xie.main; import java.awt.BorderLayout; import java

vue入门模板——只需一个html

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>vue模板</title> <link rel="stylesheet" type="text/css" href="//unpkg.com/[email protected]/lib/theme-chalk/index.css"

分享一个展示文章列表的CSS样式

最近在帮朋友处理一个网站前端显示文章列表的时候,其中有个变通的思路,现整理出来留给有需要的朋友参考及自己备忘. 显示效果为:标题左对齐,日期右对齐. 标题和日期中间用常规的原点(“.”) 代替,显示效果如下图所示. 至于第一点要求,很容易就实现了,将日期显示的东东,加上 “ float:right “基本上就搞定了. 但第二点要求: 中间显示原点这个试了很多方式: 比如后台在返回数据的时候,根据标题文字长度自动补齐原点字符串一起返回到前端展示. 或者在前端通过js计算字符长度然后补齐. 但最后展

parcel+vue入门

一.parcel简单使用 npm install -D parcel-bundler npm init -y (-y表示yes,跳过项目初始化提问阶段,直接生成package.json 文件.) Parcel 可以使用任何类型的文件作为入口,但是最好还是使用 HTML 或 JavaScript 文件.如果在 HTML 中使用相对路径引入主要的 JavaScript 文件,Parcel 也将会对它进行处理将其替换为相对于输出文件的 URL 地址. 接下来,创建一个 index.html 和 ind