Web前端之路架构社区成为技术大神

Vue基础

2018-05-29  本文已影响145人  他爱在黑暗中漫游

相关概念

混合开发和前后端分离

库和框架

什么是Vue

什么是Vue

Vue的特点

Vue初体验

安装Vue

下载Vue

Hello World

通过数据绑定的方式,在界面上展示Hello World

<div id="app">
    <h1>{{ msg }}</h1>
</div>
<script src="vue.js"></script>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            msg: 'Hello World'
        }
    });
</script>

Vue实例

创建Vue实例

每一个Vue应用都是通过Vue构造函数创建一个Vue的实例开始

var vm = new Vue({
    // Vue的选项
});

模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。

插值表达式

数据绑定最常见的形式就是使用“Mustache”语法 (双大括号) 的文本插值:

<h1>
    {{ msg }}
</h1>

JavaScript表达式

对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。

{{ number + 1 }}

{{ age > 18 ? '年满18岁' : '未满18岁' }}

{{ message.split('').reverse().join('') }}

<h1>
    {{ msg }}
</h1>

注意:差值表达式中不能写语句。例如:var a = 10;

指令

指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式(v-for 是例外情况,稍后我们再讨论)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。参考文档

v-html/v-text

v-bind

可以绑定标签上的任何属性。

v-model

表单元素的绑定

v-on

v-show

v-if

v-for

v-cloak

v-once

Vue的选项对象

当创建一个 Vue 实例时,你可以传入一个选项对象。你可以在 API 文档 中浏览完整的选项列表。

案例:表格操作

总结:

DevTools

https://github.com/vuejs/vue-devtools

MVVM

MVVMPattern.png

其它知识点

过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。

需求:对表格案例中的日期进行格式化。

<td>{{ item.date | fmrTime('YYYY-MM-DD HH:mm:ss') }}</td>
<script>
Vue.filter('fmrTime', function (time, formatStr) {
    // 使用moment.js对日期进行格式化
    return moment(time).format(formatStr);
});
</script>

计算属性

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。

通过获取时间,演示计算属性和methods中方法的区别(缓存数据的差异)。

计算属性和方法的区别

  1. 方法每次调用都会执行
  2. 计算属性只有当依赖的数据方法变化才会执行

需求:表格案例中实现搜索功能

<tr v-for="(item, index) in newList" :key="index">
....
<tr v-if="newList.length === 0">
<script>
    var vm = new Vue({
        el: ....
        computed: {
            newList() {
              return this.list.filter((item) => {
                return item.name.startsWith(this.searchKey);
              });
            }
          }
    })
</script>

ref

在Vue.js中操作DOM。

需求:表格案例中让文本框默认获得焦。

  1. 给要获取焦点的元素增加ref属性
  2. 在mounted中通过$refs获取DOM元素
<input type="text" ref="username" v-model="name">

<script>
    var vm = new Vue({
       el: '#app',
       // mounted当页面加载完毕执行
       mounted: function () {
           this.$refs.username.focus();
       },
       data.....,
    });
</script>

注意:Vue.js中不推荐直接操作DOM,除非必须否则不建议这么使用。

自定义指令

除了核心功能默认的指令,例如:v-modelv-show,Vue 也允许注册自定义指令。

需求:表格案例中让文本框默认获得焦。 给文本框增加自定义指令 v-focus

<input type="text" v-focus v-model="name">
<script>
// 全局自定义指令
Vue.directive('focus', {
    inserted: function (el) {
        el.focus();
    }
});
</script>

发送网络请求

在Vue.js中发送网络请求本质还是ajax,我们可以使用插件方便操作。

axios

既可以在浏览器端又可以在node.js中使用的发送http请求的库,支持Promise,默认不支持jsonp。官网

表格案例

过渡和动画

Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。

在 CSS 过渡和动画中自动应用 class

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

// v要替换成transition组件的name属性值
v-enter:定义进入过渡的开始状态。
v-enter-active:定义进入过渡生效时的状态。
v-enter-to: 2.1.8版及以上 定义进入过渡的结束状态。
v-leave: 定义离开过渡的开始状态。
v-leave-active:定义离开过渡生效时的状态。
v-leave-to: 2.1.8版及以上 定义离开过渡的结束状态。

示例:

<style>
    .box {
        position: absolute;
        left: 0;
        top: 50px;
        width: 100px;
        height: 100px;
        background-color: red;
    }
    .slide-enter, .slide-leave-to {
        left: 200px;
        opacity: 0;
    }
    .slide-enter-active, .slide-leave-active {
        transition: all 2s;
    }
    .slide-enter-to, .slide-leave {
        left: 0px;
        opacity: 1;
    }
</style>
<button @click="isShow = !isShow">显示/隐藏</button>

<transition name="slide"> 
    <div v-show="isShow" class="box"></div>
</transition>
<script>
    var vm = new Vue({
      el: '#app',
      data: {
        isShow: true
      }
    });
</script>

自定义过渡动画的类名

可以通过transition组件自定义过渡动画的类名,可以方便结合第三方的动画库使用,比如:animate.css

// transition组件的属性 
enter-class
enter-active-class
enter-to-class (2.1.8+)
leave-class
leave-active-class
leave-to-class (2.1.8+)

示例:


<button @click="isShow = !isShow">toggle</button>
<transition 
            enter-active-class="animated fadeIn"
            leave-active-class="animated fadeOut">
    <div v-show="isShow">hello</div>
</transition>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            isShow: true
        }
    });
</script>

组件

什么是组件

组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

components.png

组件和模块

b25efd3e8af188b5ab36ccb66baddd71_hd.jpg

Vue中的组件开发

组件是可复用的 Vue 实例,且带有一个名字,比如 <my-breadcrumb>。把这个组件作为自定义元素来使用。组件的好处是写一次可以进行任意次数的复用。

组件参考文档

全局组件

Vue.component('my-breadcrumb', {
      template: `<div>
          <span>{{ level1 }}</span>
          <span>/</span>
          <span @click="t">{{ level2 }}</span>
        <div>`,
      data() {
        return {
          level1: '用户管理1',
          level2: '用户列表1'
        };
      },
      methods: {
        t() {
          alert('hello');
        }
      }
    });

注意:

  1. 组件的模板中必须有且只有一个根标签
  2. 组件是一个特殊的Vue实例
  3. 组件中的data是一个方法,目的是让每一个组件维护一个自己的数据
  4. 组件有自己的作用域

私有组件

// 私有组件
var ComponentA = {
    template: '<div>{{ msg }}</div>',
    data() {
        return {
            msg: 'hello'
        };
    }
};
var vm = new Vue({
    el: '#app',
    components: {
        'component-a': ComponentA
    }
});

通过Props给子组件传值

  1. 子组件可以通过 props 选项接收一个一些值,通过 props 传递的值变成了改组件的一个属性。

    var ComponentA = {
        template: '<div>{{ title }}</div>',
        props: ['title'],
    };
    
  2. 当然子组件具有 props 选项后,数据可以通过标签的自定义属性传递给子组件

    <component-a :title="msg"></component-a>
    
  3. 在vue的实例中提供该属性值

    var vm = new Vue({
        el: '#app',
        data: {
            msg: 'hello heima',
        },
        components: {
            'component-a': ComponentA
        }
    });
    

Vue实例的生命周期

//创造vue实例之后运行此函数,vm中的data/methods中的成员不可用
beforeCreate: function () {
   console.log("beforeCreate")
}
//创造vue实例之后运行此函数,vm中的data/methods属性可用
created: function () {
  console.log("created")
}
//当vue实例的el节点或组件挂载到页面以前运行次函数
beforeMount: function () {
    console.log("beforeMount")
}
//当vue实例的el节点或组件挂载到页面以后运行次函数
mounted: function () {
    console.log("mounted")
}
//当vue实例数据发生改变前触发此函数
beforeUpdate: function () {
    console.log("beforeUpdate")
}
//当vue实例数据发生改变后触发此函数
updated: function () {
    console.log("updated")
}

前端路由

单页应用

vue-router

快速体验

  1. 导入vue和vue-router

  2. 设置HTML中的内容

    <!-- router-link 最终会被渲染成a标签,to指定路由的跳转地址 -->
    <router-link to="/users">用户管理</router-link>
    
    <!-- 路由匹配到的组件将渲染在这里 -->
    <router-view></router-view>
    
  3. 创建组件

    // 创建组件
    // 组件可以放到单独的js文件中
    var Home = {
        template: '<div>这是Home内容</div>'
    };
    var Users = {
        template: '<div>这是用户管理内容</div>'
    };
    
  4. 配置路由规则

    // 配置路由规则
    var router = new VueRouter({
        routes: [
            { name: 'home', path: '/', component: Home },
            { name: 'users', path: '/users', component: Users }
        ]
    });
    
  5. 设置vue的路由选项

    var vm = new Vue({
        el: '#app',
        router
    });
    

动态路由匹配

假设有一个用户列表,想要删除某一个用户,需要获取用户的id传入组件内,如何实现呢?

此时可以通过路由传参来实现,具体步骤如下:

  1. 路由规则中增加参数,在path最后增加 :id

    { name: 'users', path: '/users/:id', component: Users },
    
  2. 通过 <router-link> 传参,在路径上传入具体的值

    <router-link to="/users/120">用户管理</router-link>
    
  3. 在组件内部可以使用,this.$route 获取当前路由对象

    var Users = {
        template: '<div>这是用户管理内容 {{ $route.params.id }}</div>',
        mounted() {
            console.log(this.$route.params.id);
        }
    };
    

webpack

webpack 是一个模块打包器。webpack 的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用。

参考网站: 中文参考网站 官网

安装webpack

最新webpack版本4.x

  1. 本地安装webpack
  2. 安装webpack的命令行工具 webpack-cli
$ npm install webpack webpack-cli --save-dev

快速实践

参考官网

  webpack-demo
  |- package.json
+ |- /dist
+ |- index.html
  |- /src
    |- index.js

math.js

export default {
  add(a, b) {
    return a + b;
  },
  sub(a, b) {
    return a - b;
  }
};

index.js

import Math from './math';

var x = 5;
var y = 6;

console.log(Math.add(5, 6));
console.log(Math.sub(5, 6));
$ npx webpack

配置文件 webpack.config.js

webpack4.x 以前,必须要有配置文件。在 webpack 4.x 以后,可以无须任何配置使用(),然而大多数项目会需要很复杂的设置,这就是为什么 webpack 仍然要支持。

webpack常用的Loader

webpack 最出色的功能之一就是,除了 JavaScript,还可以通过 loader 引入任何其他类型的文件。webpack 可以把所有文件作为模块,动态打包(dynamically bundle)所有依赖项。

参考文档

打包CSS

打包less

打包sass

加载图片

使用 file-loader 可以加载图片和字体

加载字体

webpack常用插件

除了通过loader去处理不同的资源文件以外,webpack还支持插件机制,通过插件可以完成更多的事情。

HtmlWebpackPlugin

自动生成index.html,并引入资源文件,还可以通过配置压缩HTML。

CleanWebpackPlugin

清空dist目录。

使用source map

参考文档

在webpack.config.js中添加

devtool: 'inline-source-map',

使用 webpack-dev-server

webpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。让我们设置以下:

$ npm install --save-dev webpack-dev-server

webpack.config.js

devServer: {
    contentBase: './dist'
},

package.json

"start": "webpack-dev-server --open"

启用HMR

模块热替换(Hot Module Replacement 或 HMR)是 webpack 提供的最有用的功能之一。它允许在运行时更新各种模块,而无需进行完全刷新。

webpack.config.js

const webpack = require('webpack');

.......
devServer: {
    contentBase: './dist',
    hot: true
},
.......

.......
     new webpack.NamedModulesPlugin(),
     new webpack.HotModuleReplacementPlugin()
.......

综合案例

单文件组件

可以通过 .vue 文件封装组件,参考文档

案例演示

image-20180526145007221.png

搭建项目结构

配置根组件

提取子组件

使用 Vue-Router 实现页面导航管理

Vue-Router 能帮我们实现点击某个导航链接的时候动态的展示一个组件

JSON Server

可以快速开启 REST API 测试服务器的工具命令行工具。官网

安装

$ npm install json-server -g

使用

$ json-server --watch db.json

接口地址

实现项目功能

安装 axios 到项目中

 $ npm install axios --save

英雄列表

JS

import axios from 'axios';
export default {
  data() {
    return {
      heroes: []
    };
  },
  mounted() {
    this.loadData();
  },
  methods: {
    async loadData() {
      const res = await axios.get('http://localhost:3000/heros');
      this.heroes = res.data;
    }
  }
};

HTML

<tr v-for="(item, index) in heroes" :key="item.id">
    <td>{{ index + 1 }}</td>
    <td>{{ item.name }}</td>
    <td>{{ item.gender }}</td>
    <td>
        <!-- <router-link :to="'/edit/' + item.id"></router-link> -->
        <a href="edit.html">edit</a>
        &nbsp;&nbsp;
        <a href="javascript:window.confirm('Are you sure?')">delete</a>
    </td>
</tr>

删除英雄

HTML

<!-- prevent 修饰符,阻止后续内容的执行 -->
<a href="#" @click.prevent="handleClick(item.id)">delete</a>

JS

async handleClick(id) {
    const isConfirmed = confirm('确认要删除该英雄?');
    if (!isConfirmed) {
        return;
    }
    const res = await axios.delete(`http://localhost:3000/heros/${id}`);
    if (res.status === 200) {
        this.loadData();
        alert('删除成功');
    } else {
        alert('删除失败');
    }
}

添加英雄

路由

HTML

<h2 class="sub-header">添加英雄</h2>
<form>
    <div class="form-group">
        <label for="name">英雄名称</label>
        <input type="text" v-model="formData.name" class="form-control" id="name" placeholder="英雄名称">
    </div>
    <div class="form-group">
        <label for="sex">英雄性别</label>
        <input type="text" v-model="formData.gender" class="form-control" id="sex" placeholder="英雄性别">
    </div>
    <button type="submit" @click.prevent="handleAdd" class="btn btn-success">Submit</button>
</form>

JS

import axios from 'axios';

export default {
  data() {
    return {
      formData: {
        name: '',
        gender: ''
      }
    };
  },
  methods: {
    async handleAdd() {
      const res = await axios.post('http://localhost:3000/heros', this.formData);
      if (res.status === 201) {
        // 跳转到列表页面
        this.$router.push({
          name: 'heroes'
        });
      } else {
        alert('添加失败');
      }
    }
  }
};

编辑英雄

路由

HTML

和添加英雄一样

JS

import axios from 'axios';

export default {
  data() {
    return {
      formData: {
        name: '',
        gender: ''
      },
      heroId: -1
    };
  },
  created() {
    this.heroId = this.$route.params.id;
    this.getHeroById();
  },
  methods: {
    // 根据id,获取英雄信息
    async getHeroById() {
      const res = await axios.get(`http://localhost:3000/heros/${this.heroId}`);
      if (res.status === 200) {
        this.formData = res.data;
      }
    },
    // 更新英雄信息
    async handleEdit() {
      const res = await axios.patch(`http://localhost:3000/heros/${this.heroId}`, this.formData);
      if (res.status === 200) {
        // 跳转到列表页面
        this.$router.push({
          name: 'heroes'
        });
      } else {
        alert('编辑失败');
      }
    }
  }
};

NPM 缓存安装

需要曾经从网络使用NPM安装过想要的包

$ npm --cache-min 9999999 install webpack --save-dev
上一篇下一篇

猜你喜欢

热点阅读