Vue.js /vju:/

数据驱动+组件化的前端开发

What are Vue.js 弄啥嘞?

  • 一个轻量的 MVVM 前端框架
 UI = VM(State)
  • MVVM?
    • ​Model - View - ViewModel
    • 数据改变, UI 随之改变
    •  

Vue.js 闪光点

  • 专注于视图(View)层
  • 数据驱动
  • 上手简单、简洁优雅的 API
  • 快速、高性能
  • 基于组件
  • 轻量且无其他库的依赖 (~24kb min+gzip)

Vue.js – Intro

专注于视图(View)层

  • Vue 类似于 React 只是 MV* 架构中的视图层
  • 虽然作者灵感来源于 Angular,但有本质的差别:
    • Angular 是大而全的“重”框架
    • 数据绑定机制不同
  • 与 Angular/React/Ember/Ployer/Riot 的对比看 这个链接

Vue.js – Intro

数据驱动

  • 模板表达式
  • 计算属性
  • 自动追踪依赖

Vue.js – Intro

上手简单、简洁优雅的 API

  • 一点儿 HTML 模板
  • 一点儿 JSON 数据
  • 创建一个 Vue 实例
  • 搞定...

Vue.js – Intro

<!-- HTML -->
<div id="demo">
  <p>
    {{msg ? msg : "no content"}}
  </p>

  <input type="text" v-model="msg">
</div>
// json 数据
var jsonData = {
  msg: 'Hello Vue.js!'
};

// vue 实例
var vm = new Vue({
  el  : '#demo',
  data: jsonData
});

举个栗子

Vue.js – Intro

Vue 中的指令缩写

<!-- 1. 动态绑定一个或多个属性 -->
<!-- 绑定 attribute -->
<img v-bind:src="imageSrc">

<!-- 缩写 -->
<img :src="imageSrc">

<!-- 绑定 class -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]"></div>

<!-- 绑定 style -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>

<!-- 2. 绑定事件: click、submit、keyup...甚至自定义事件如 my-event -->
<a v-on:click="someFunc"></a>

<a @click="someFunc"></a>
<my-component @my-event="handleThis"></my-component>

Vue.js – Intro

快速、高性能

  • 精确有效的异步批量 DOM 更新
  • 尤其对比于 Angular 1 的脏检查
vm.msg = 'one';
vm.msg = 'two';
vm.msg = 'three';
// 只会触发一次 DOM 更新

Vue.js – Intro

基于组件

  • 使用解耦、可复用的组件来构造界面
  • 基本步骤:
    • 定义
    • 注册
    • 使用

Vue.js – Intro

// 组件定义
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
  // template: '#tmpl'
});

// 全局注册
Vue.component('my-component', MyComponent);

// 创建根实例
new Vue({
  el: '#example'
});

组件栗子

<!-- 组件的使用 -->
<div id="example">
  <my-component></my-component>
</div>

<!-- template 使用 id

<template id="tmpl">
  <div>
    A custom component!
  </div>
</template>

-->
<!-- HTML -->
<div id="example">
  <div>A custom component!</div>
</div>

Vue.js – Intro

组件间的数据交流

1. props

  • 定义组件数据的传递
  • 3种绑定方式

2. event

  • 通过事件和回调传递
  • 多种信息传递方式

3. inherit

  • 继承
  • 1.0版本后已被废弃
Vue.component('child', {
  // 声明 props
  props: ['msg'],
  // prop 可以用在模板内
  // 可以用 `this.msg` 设置
  template: '<span>{{msg}}</span>'
});
<!-- 默认为单向绑定 -->
<child :msg="parentMsg"></child>
<!-- 双向绑定 -->
<child :msg.sync="parentMsg"></child>
<!-- 单次绑定 -->
<child :msg.once="parentMsg"></child>
// 监听某一个事件
$on('create-alert', () => { ... })
// 在同一个组件里触发事件
$emit('create-alert', { ... })
// 向上传递一个事件
$dispatch('create-alert', { ... })
// 向下所有的组件传递一个事件
$broadcast('create-alert', { ... })

Vue.js – Intro

轻量且无其他库的依赖

  • 开启 min+gzip ~24kb
  • vue 2.0:
    • min+gzip ~12kb
    • 加编译器 min+gzip ~17kb
  • React 15 min+gzip ~44kb
  • Angular 就不提了...

Vue.js – Intro

栗子展示

Vue.js – Examples

列表渲染

<!-- HTML -->
<div id="app">
  <ul>
    <li v-for="todo in todos">
      {{todo.text}}
    </li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue.js' },
      { text: 'Build Something Awesome' }
    ]
  }
});

Vue.js – Examples

处理用户输入

<!-- HTML -->
<div id="app">
  <p>{{msg}}</p>
  
  <button 
    v-on:click="reverseMsg">
    Reverse Message
  </button>
</div>
var vm = new Vue({
  el: '#app',
  data: { msg: 'Hello Vue.js!' },
  methods: {
    reverseMsg: function() {
      this.msg = this.msg.split('')
                         .reverse()
                         .join('');
    }
  }
});

Vue.js – Examples

结合以上

<!-- HTML -->
<div id="app">
  <input 
    v-model="newTodo" 
    v-on:keyup.enter="addTodo">

  <ul>
    <li v-for="todo in todos">
      <span>{{todo.text}}</span>

      <button v-on:click="rmTodo($index)">X</button>
    </li>
  </ul>
</div>
var vm = new Vue({
  el: '#app',
  data: {
    newTodo: '',
    todos: [
      { text: 'Add some todos' }
    ]
  },
  methods: {
    addTodo: function () {
      var text = this.newTodo.trim();

      if (text) {
        this.todos.push({ 
          text: text 
        });

        this.newTodo = '';
      }
    },
    rmTodo: function (index) {
      this.todos.splice(index, 1);
    }
  }
});

Vue.js – Examples

极简的 markdown 编辑器

<!-- HTML -->
<div id="editor">
  <textarea v-model="input" debounce="300"></textarea>
  <div v-html="input | marked"></div>
</div>
var vm = new Vue({
  el: '#editor',
  data: {
    input: '# hello'
  },
  filters: {
    marked: marked
  }
});

Vue.js – Examples

表格组件

Vue.js – Examples

SVG 图形

Vue.js – Examples

更多栗子参见

vuejs.org.cn/examples/

Vue.js – Examples

Vue.js – Basics

// Object.defineProperty
// getter / setter / watcher object

var a = {};

Object.defineProperty(a, 'b', {
  enumerable: false,
  value: "static",
  get: () => { ... },
  set: () => { ... }
});

Vue.js 的实现原理

如果需要构建大型应用,那么可能还需要以下的工具...

构建大型应用

Vue-cli

  • Webpack / Browerify
  • Hot reloading
  • Linting
  • Unit/e2e tests
  • CSS extraction

Vue ecosystem

  • Vue-router
  • Vuex
  • Vue-devtools
  • Vue-touch
  • Vue-validation
  • and more...

Vue.js – Basics

单文件组件

Vue.js – Basics

带预处理器的

单文件组件

Vue.js – Basics

scoped 属性

注意:scoped 不会影响 css的作用优先级,因此使用 scoped 不代表不会被外部样式所覆盖!

可以将该样式限制在此组件内部,从而不会与外部同名样式形成冲突。

Vue.js – Basics

Vue.js – jQuery

Vue.js VS jQuery

  • What VS How
  • 声明式 VS 命令式
  • 操作数据 VS 操作 DOM

Vue.js VS jQuery

<div id="demo">
  <p>hello jQuery!</p>

  <input type="text" value="hello jQuery!">
</div>
// 1.(手动)找到 input 节点
var $input = $('#demo > input');

// 2.(手动)找到 p 节点
var $p = $('#demo > p');

// 3.(手动)监听键盘事件
$input.keyup(function() {
  var newText = $input.val() ? 
                $input.val() : 
                'no content';

  // 4.(手动)更新 dom
  $p.text(newText);
});

Vue.js – jQuery

Vue.js VS jQuery

  • jQuery 的处理逻辑是【命令式】地【手动】地【操作 DOM】,即在不断地处理怎么(how)做的问题。并且 jQuery 代码往往和 DOM 结构强耦合,不利于修改、单元测试等。
  • Vue.js 的处理逻辑是【声明式】地绑定数据和 DOM 后,直接【操作数据】(几乎不直接操作 DOM),即只关心是什么(what)的问题。基于组件接口,可以方便地修改和编写单元测试。

Vue.js – jQuery

我理解的前端开发

UE

Front End

 

 

Back End

 

Project Manager

*.psd

api

Quality

Assurance

Server Side Render

Node.js

Vue.js – jQuery

Vue-Router

Vue.js – Plugins

import Vue from 'vue';
import Router from 'vue-router';
import App from './app.vue';
import ViewA from './view-a.vue';
import ViewB from './view-b.vue';

Vue.use(Router);

const router = new Router();

router.map({
  '/a': { component: ViewA },
  '/b': { component: ViewB }
});

router.start(App, '#app');
<div>
  <h1>This is the layout that won't change</h1>
  <router-view>
    <!-- matched component renders here -->
  </router-view>
</div>

Vue.js – Plugins

vuex

Vuex 栗子

import Vuex from 'vuex';

const state = { counter: 0 };

const mutations = {
  INCREMENT (state) { state.counter++ }
};

export default new Vuex.Store({
  state,
  mutations
});
store.dispatch('INCREMENT');

console.log(store.state.count); // -> 1

Vue.js – Plugins

Vue.js – Plugins

Vuex 栗子说明

Vue.js – Plugins

Vue-devtools

Vue.js – 2.0

Vue.js 2.0

  • 轻量级 virtual-DOM(不再是Browser-Only)
    • 可以像之前一样让编译器在浏览器中运行 ~17kb
    • 也可以将模板预编译后直接运行                 ~12kb​
    • 不需要额外的工作就获得优化的重渲染
    • 不需要 shouldComponentUpdate 或 immutable 数据
  • 流式服务器端渲染(Streaming Server-side Rendering)
    • 既然引入 v-dom 自然支持 ssr 和客户端的 hydration
    • 解决同步渲染阻塞的痛点:渲染时返回可读 stream 直接 pipe 到 HTTP 的 responce
  • 移动端 native 的探索:weex(by 阿里无线事业部)

Vue.js – ref

参考资料

关于 Vue.js 的小介(an)绍(li)~

By steve young

关于 Vue.js 的小介(an)绍(li)~

骚年,你听说过 Vue 吗?

  • 2,641