Vuejs 2.0 入门不指南

自我介绍

龙佳文(ID:Awe)

罗辑思维前端工程师

Vuejs 开发者、安利师,开源爱好者。

主要讲什么

  1. Vue 1.x VS 2.0 API 变化
  2. Vue 2.0 新增特性

变化

  1. 全局配置
  2. 全局 API
  3. 生命周期
  4. 实例方法
  5. 指令 API

全局配置

- Vue.config.silent

- Vue.config.devtools

- Vue.config.errorHandler

- Vue.config.keyCodes

- Vue.config.optionMergeStrategies

 

日志和警告

Vue.config.silent = true

禁止所有 Vue 的日志和警告

Vue开发工具

Vue.config.devtools = true

是否允许 Vue 开发者工具检查的配置。

默认值在开发环境中为 `true` ,生产环境中为 `false`。你可以将其设置为 `true`,以便检查生产环境中调试。

未捕获错误收集

Vue.config.errorHandler = function (err, vm) {
  console.log(err, vm)
}

配置一个全局的钩子函数用于收集在组件渲染和数据观察中未被捕获的错误

自定义键盘修饰符

Vue.config.keyCodes = { esc: 27 }

自定义 Vue 中 v-on 监听键盘事件的键盘 `keyCode` 的别名 

<input type="text" @keyup.esc="removeTop">

全局 API

新增

Vue.compile

 

废弃

Vue.partial (使用 函数式组件 代替)

Vue.elementDirective (直接使用组件)

Vue.compile

var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
  data: {
    msg: 'hello'
  },
  render: res.render,
  staticRenderFns: res.staticRenderFns
})

将模板字符串编译为→ `render` 函数

只有在独立版本可用

生命周期

实例方法

  • 数据
  • 事件
  • DOM

 

 

数据

- vm.$watch
- vm.$get 废弃,直接通过实例对象取值
- vm.$set 废弃,使用 Vue.set
- vm.$delete 废弃,使用 Vue.delete
- vm.$eval 废弃,没什么卵用
- vm.$interpolate 废弃,还是没什么卵用
- vm.$log 废弃,推荐使用 Vue 开发工具

事件

- vm.$on
- vm.$once
- vm.$off
- vm.$emit
- vm.$dispatch 废弃,使用一个全局 `event bus` 或者 VueX 代替
- vm.$broadcast 废弃同上

DOM


- vm.$nextTick
- vm.$appendTo 废弃,直接在 `vm.$el` 上使用原生 DOM API
- vm.$before 废弃
- vm.$after 废弃
- vm.$remove 废弃

指令 API

调整:

  v-for 

  自定义插件 API

 

废弃:

  v-el

  v-ref

v-for 参数

<ul id="example-2">
  <li v-for="(item, index) in arr">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
<ul id="example-3">
  <li v-for="(item, key, index) in Obj">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>

这样在数组或者对象遍历时获取 index

key 代替 track-by


<div v-for="item in items" :key="item._uid">
  <!-- content -->
</div>

<div v-for="item in items" :key="index">
  <!-- content -->
</div>

自定义指令的 API 

// example directive
export default {
  bind (el, binding, vnode) {
    // binding 对象有 value, oldValue, expression, arg 和 modifiers 属性
    binding.expression // "a.b"
    binding.arg // "arg"
    binding.modifiers // { modifier: true }
    // Vue 实例的上下文可以通过 vnode.context 访问
  },

  // update 增加了 oldVnode
  update (el, binding, vnode, oldVnode) { ... },
  // componentUpdated 是一个新钩子函数,它在整个组件完成当前更新周期被调用。这意味着这个钩子被调用的时候是所有的DOM都会处于更新状态。也就是说他被调用时不一定意味着绑定对象值被更新。
  componentUpdated (el, binding, vnode, oldVNode) { ... },

  unbind (el, binding, vnode) { ... }
}

bind 

el:绑定指令的DOM元素

binding:包含 name, value ,oldValue,expression,arg,modifier。

vnode:Vue 编译的当前元素的 虚拟节点,可以通过 VNode API 操作。

 

bind (el, binding, vnode) {}

update

update 比 bind 多了一个 oldVnode 参数

 

update (el, binding, vnode, oldVnode) { ... },

componentUpdated

在组件更新之后就会调用

componentUpdated (el, binding, vnode, oldVNode) { ... }

新特性

  1. 更强大的过渡系统
  2. render 函数和函数式组件
  3. 服务端渲染

<transition>

  
  <transition name="slide-fade">
    <p v-if="show">hello</p>
  </transition>

 transition 也成了组件

JavaScript HOOK

<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>
// ...
methods: {
  // --------
  // ENTERING
  // --------
  beforeEnter: function (el) {
    // ...
  },
  // 混合 CSS 过渡时不用执行 done
  enter: function (el, done) {
    // ...
    done()
  },
  afterEnter: function (el) {
    // ...
  },
  enterCancelled: function (el) {
    // ...
  },
  // --------
  // LEAVING
  // --------
  beforeLeave: function (el) {
    // ...
  },
  // 混合 CSS 过渡时不用执行 done 
  leave: function (el, done) {
    // ...
    done()
  },
  afterLeave: function (el) {
    // ...
  },
  // leaveCancelled only available with v-show
  leaveCancelled: function (el) {
    // ...
  }
}

JavaScript hook 可单独或者与 CSS 结合实现过渡,在纯 JavaScript 过渡时建议使用 v-bind:css="false" 忽略 CSS检测,提升效率

列表过渡

 <transition-group name="list" tag="p">
    <span v-for="item in items" v-bind:key="item" class="list-item">
      {{ item }}
    </span>
 </transition-group>

<transition-group> 会以 name 为 tagName呈现为一个真实元素

内部子元素要指定唯一的key

render fuction

new Vue({
  el: '#app',
  render: h => h(App)
})

比模板更灵活

createElement

createElement(tagName, data, children)

createElement('user', {
    props: {
        user: this.currentUser
    },
    on: {
        click: this.clickHandler
    }
})

createElement 能接受三个参数

tagName,data,children

{
  // 普通的 HTML 属性
  attrs: {
    id: 'foo'
  },
  // 组件 props
  props: {
    myProp: 'bar'
  },
  // DOM 属性
  domProps: {
    innerHTML: 'baz'
  },
  // 事件监听器基于 "on"
  // 所以不再支持如 v-on:keyup.enter 修饰器
  // 需要手动匹配 keyCode。
  on: {
    click: this.clickHandler
  },
  // 仅对于组件,用于监听原生事件,而不是组件使用 vm.$emit 触发的事件。
  nativeOn: {
    click: this.nativeClickHandler
  },
  // 和 `v-bind:class` API 一致
  'class': {
    foo: true,
    bar: false
  },
  // 和 `v-bind:style` API 一致
  style: {
    color: 'red',
    fontSize: '14px'
  },
  // 其他特殊顶层属性
  key: 'myKey',
  ref: 'myRef'
}

简单上手

<ul v-if="items.length">
  <li v-for="item in items">{{ item.name }}</li>
</ul>
<p v-else>No items found.</p>
render: function (createElement) {
  if (this.items.length) {
    return createElement('ul', this.items.map(function (item) {
      return createElement('li', item.name)
    }))
  } else {
    return createElement('p', 'No items found.')
  }
}

手写 render 函数还是挺麻烦的事

JSX

import User from './User.vue'
new Vue({
  el: '#demo',
  data: {
    User: {...}
  },
  render (h) {
    return (
      <User user={this.User}>
      </User>
    )
  }
})

我觉得,还是看模板正常一点

函数式组件

Vue.component('my-component', {
  functional: true,
  // 为了弥补缺少的实例
  // 提供第二个参数作为上下文
  render: function (createElement, context) {
    // ...
  },
  // Props 可选
  props: {
    // ...
  }
})

服务端渲染

  • SEO(搜索引擎优化)
  • 弱网可用
  • 没有 JavaScript 的浏览器?

Hello World

// 步骤 1:创建一个Vue实例
var Vue = require('vue')
var app = new Vue({
  render: function (h) {
    return h('p', 'hello world')
  }
})
// 步骤 2: 创建一个渲染器
var renderer = require('vue-server-renderer').createRenderer()
// 步骤 3: 将 Vue实例 渲染成 HTML
renderer.renderToString(app, function (error, html) {
  if (error) throw error
  console.log(html)
  // => <p server-rendered="true">hello world</p>
})

服务端渲染的三种姿势

  • renderer.renderToString(vm, cb)
  • renderer.renderToStream(vm)
  • createBundleRenderer(code, options)

统一的数据API请求

  • axios 
  • 野狗
  • Leancloud
  • ...

 

服务端组件缓存

Vue.component({
  name: 'list-item',
  template: '<li>{{ item.name }}</li>',
  props: ['item'],
  serverCacheKey: function (props) {
    return props.item.type + '::' + props.item.id
  }
})
var createRenderer = require('vue-server-renderer').createRenderer
var lru = require('lru-cache')
var renderer = createRenderer({
  cache: lru(1000)
})

Thanks

Made with Slides.com