Vue.js 的组件化编程

💗 ming @ xitu.io 💗

1. Vue.js?
2. 组件化
3. 我们咋用的

阴明

Ming Yin

稀土创始人 🙄

前端工程师 🐶

二流设计师 🙀

 

 

ming@xitu.io

ming.today

@kalasoo

Vue.js

Reactive Components for Modern Web Interfaces

数据驱动的组件,为现代化的 Web 界面而生

尤小右 Evan You

@youyuxi

多说  / Google / Meteor

发布于 2014 年 2 月

Vue.js 主要是干啥的?

它是一个 MVVM 前端框架

MVVM?

  • Model - View - ViewModel
  • State - UI - ? 
    • ViewModel
    • 当数据改变的时候
    • UI 也自动改变
 UI = VM(State)

一个前端框架?

  • 基于一定的准则写

  • 写起来更容易

  • 代码更易维护

  • 网站的业务逻辑可以不断扩展

  • 性能可以满足需求

Example

<div id="demo">
  <p>{{message ? message : "no content"}}</p>
  <input v-model="message">
</div>
var demo = new Vue({
  el: '#demo',
  data: {
    message: 'Hello Vue.js!'
  }
})

CodePen 加载中

Vue.js 怎么实现的?

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

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

Vue.js Community?

v1.0.21

大量的配套工具

vue-loader

vue-cli

vue-router

NPM 总下载 58 万+

>8K D/M

主页超过 400 万的 PV

及我这种无良的 👏👏👏

Vue.js / Angular.js / React.js

我就是喜欢,我就是任性,我就是主观 #认真脸# 😳

为什么很多人接触了 Vue.js 后很快就爱上了它?

  1. 它的语法很简单
  2. 它的学习曲线并不陡峭
  3. 比 Angular 快,比 React 轻(实现原理不同)
  4. 它同样性感地结合着新的轮子
  5. 它可以支持较为复杂的大型产品
  6. 它的组件管理很方便(Single File Components)
  7. 它的文档和官网都很好看且易读

Vue.js 的组件化

Why - How - What

Why?

😼 因为爽 😼

人同时可以处理的信息是有限的

这是你搞不定的

一大堆东西

这是你搞得定的一堆小东西

和你能搞得定的一个关系网

How?

  1. 定义一个组件
  2. 加载一个组件
  3. 使用一个组件
  4. 组建的生命周期
  5. 组件间的数据传输

What?

Vue.js Component System

// app.js 定义
var MyComponent = Vue.extend({
  template: '<div>A custom component!</div>'
})
// app.js 注册
Vue.component('my-component', MyComponent)
// app.js 创建根实例
new Vue({
  el: '#example'
})
<!-- HTML -->
<div id="example">
  <my-component></my-component>
</div>

<script src="app.js"></script>
<div id="example">
  <div>A custom component!</div>
</div>

vue-loader

Single File Components

// comment.vue
<style lang="sass">
button {
    border: 1px solid gray;
    &.blue { border-color: blue; }
}
</style>

<template lang="jade">
avatar(:user='user')
input(type='text', v-model='content')
button.blue(@click='submitComment')
</template>

<script>
import Comment from '../models'
import avatar  from './components/avatar.vue'

export default {
    props: ['user'],
    components: {
        avatar
    },
    data () {
        return {
            content: ''
        }
    },
    methods: {
        submitComment (e) {
            e.preventDefault();
            var comment = new Comment(this.content)
            comment.save().then(() => {
                alert('评论成功')
                this.content = ''
            })
        }
    }
}
</script>

.vue: 一个文件来管理一个组件

  1. 样式:<style>
  2. 内容:<template>
  3. 行为:<script>
  4. 扩展:lang=" ... "
  5. 合作:彼此间源引

webpack

A module bundler

一个模块打包工具

  • 各种资源都是模块
  • 分开独立请求 js / css / ...
  • 打包合并成一个文件
  • 大型产品按需加载
  • ...
var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  resolveLoader: {
    root: path.join(__dirname, 'node_modules'),
  },
  module: {
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test: /\.js$/,
        loader: 'babel!eslint',
        exclude: /node_modules/
      },
      {
        test: /\.html$/,
        loader: 'vue-html'
      }
    ]
  }
}
.
├── index.html
├── main.js
├── components
│   ├── App.vue
│   ├── ComponentA.vue
│   └── ComponentB.vue
├── package.json
└── webpack.config.js
// webpack.config.js
module.exports = {
  // entry point of our application
  entry: './main.js',
  // where to place the compiled bundle
  output: {
    path: __dirname,
    filename: 'build.js'
  },
  module: {
    // `loaders` is an array of loaders to use.
    // here we are only configuring vue-loader
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue'
      }
    ]
  }
}
// main.js
var Vue = require('vue')
// require a *.vue component
var App = require('./components/App.vue')
// mount a root Vue instancenew 
Vue({
  el: 'body',
  components: {
    // include the required component
    // in the options
    app: App
  }
})
<!-- App.vue -->
<template>
  <div class="app">
    <component-a></component-a>
    <component-b></component-b>
  </div>
</template>
<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

export default {
  components: {
    ComponentA,
    ComponentB
  }
}
</script>

组件之间的数据交流

  1. props
    • 定义数据传递
    • 可三种绑定方式
  2. inherit
    • 继承
    • 1.0 后以丢弃
  3. event
    • 通过事件和回调传递
    • 多种信息传递方式
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', { ... })

What if 我们要做一个更复杂的网站?

有很多数据需要多个组件访问和调用?

vuex

一个基于  Vue.js 的 State Management 工具

 

管理那些应用级的共享数据

Vue.js Resources

这是一个大写的广告

起码也要给我 1 分钟

🔥 Thanks for your time 🔥

🔞 ming@xitu.io 🔞

🙏

Vue.js 组件化编程

By Ming YIN

Vue.js 组件化编程

Coding 线下活动上的 Vue.js 分享

  • 24,460