V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
zollero
V2EX  ›  JavaScript

Vue v2.5 调整和更新不完全详解

  •  2
     
  •   zollero · 2017-10-17 10:13:53 +08:00 · 7431 次点击
    这是一个创建于 2631 天前的主题,其中的信息可能已经有所发展或是发生改变。

    昨天升级 Vue 至 v2.5 的时候,发现有些警告,就去详细了解了下 v2.5 的更新,把内容翻译了一下,发布到了公众号。

    公众号文章地址: http://mp.weixin.qq.com/s/cce6YE6_tIJU7b2u2n1ngA

    下面把内容页贴出来,方便 V 友查看。


    近日,Vue v2.5 发布,除了对 TypeScript 的更好的支持外,还有一些功能和语法的调整,你需要了解。本文,不谈 TypeScript,只对一些主要的调整进行说明,更多详细更新内容,请参考 V2.5 Release。

    本来,对 Vue 的版本升级不怎么敏感,所以没有太关注最近的 v2.5 的发布。今天,在重新下载 Vue 构建项目的时候,发现有好几个警告提示。

    警告信息

    看警告提示,知道是因为使用了 v2.5 的 Vue,scoped slot 的语法进行了调整,然后去 GitHub 上查看了 v2.5 的 release 才知道,v2.5 中已经不建议使用 scope 属性了,推荐使用 slot-scope 属性来设置上下文。将代码中的 scope="scope" 修改为 slot-scope="scope"。如下图。

    修改后的代码

    进入正题,下面列一写 Vue v2.5 中的主要更新和调整。

    使用 errorCaptured 钩子来处理组件内异常

    在 v2.5 之前,可以用个全局的 config.errorHandler 设置来为应用提供一个处理未知异常的函数,也可以设置 renderError 组件来处理 render 函数内的异常。但是,这些都不能提供一个完整的机制来处理一个单独组件内的异常。

    v2.5 中,组件内提供了一个新的钩子函数 errorCaptured,可以捕获该组件内所有子组件树中(不含自身)产生的所有的异常(包括异步调用中的异常),这个钩子函数接收的参数和 errorHandler 一样,可以让开发者更加友好地处理组件内异常。

    如果你了解 React 的话,会发现这个特性和 React v16 中引进的“异常边界( Error Boundary )”的概念非常相似,都是为了更好的处理和展示单个组件在渲染的过程中异常。本公众号和知乎专栏之前的文章有专门介绍 React 的异常边界的概念,点击传送门进行查看。 /// 传送门加链接

    要利用 errorCaputerd,可以封装一个通用组件,来包含其他的业务组件,来捕获业务组件内的异常,并做对应的展示处理。下面列一个官方给的简单示例,封装一个通用组件(ErrorBoundary)来包含和处理其他业务组件(another component)的异常。

    Vue.component('ErrorBoundary', {
      data: () => ({ error: null }),
      errorCaptured (err, vm, info) {
        this.error = `${err.stack}\n\nfound in ${info} of component`
        return false
      },
      render (h) {
        if (this.error) {
          return h('pre', { style: { color: 'red' }}, this.error)
        }
        // ignoring edge cases for the sake of demonstration
        return this.$slots.default[0]
      }
    })
    
    <error-boundary>
      <another-component />
    </error-boundary>
    

    errorCaputed 的传递行为特性

    • 如果定义了全局的 errorHandler,所有的异常还是会传递给 errorHadnler,如果没有定义 errorHandler,这些异常仍然可以报告给一个单独的分析服务。
    • 如果一个组件上通过继承或父组件定义了多个 errorCapured 钩子函数,这些钩子函数都会收到同样的异常信息。
    • 可以在 errorCapured 钩子内 return false 来阻止异常传播,表示:该异常已经被处理,可忽略。而且,也会阻止其他的 errorCapured 钩子函数和全局的 errorHandler 函数触发这个异常。

    单文件组件支持“函数式组件”

    通过 vue-loader v13.3.0 或以上版本,支持在单文件组件内定义一个“函数式组件”,且支持模板编译、作用域 CSS 和 热部署等功能。

    函数式组件的定义,需要在 template 标签上定义 functional 属性来声明。且模板内的表达式的执行上下文是 函数式声明上下文,所以要访问组件的属性,需要使用 props.xxx 来获取。简单例子见下:

    <template functional>
      <div>{{ props.msg }}</div>
    </template>
    

    SSR 环境

    使用 vue-server-renderer 来构建 SSR 应用时,默认是需要一个 Node.js 环境的,使得一些像 php-v8js 或 Nashorn 这样的 JavaScript 运行环境下无法运行。v2.5 中对此进行了完善,使得上述环境下都可以正常运行 SSR 应用。

    在 php-v8js 和 Nashorn 中,在环境的准备阶段需要模拟 global 和 process 全局对象,并且需要单独设置 process 的环境变量。需要设置 process.env.VUE_ENV 为 "server",设置 process.env.NODE_ENV 为 "development" 或 "production"。

    另外,在 Nashorn 中,还需要用 Java 原生的 timers 为 Promise 和 settimeout 提供一个 polyfill。

    官方给出了一个在 php-v8js 中的使用示例,如下:

    <?php
    $vue_source = file_get_contents('/path/to/vue.js');
    $renderer_source = file_get_contents('/path/to/vue-server-renderer/basic.js');
    $app_source = file_get_contents('/path/to/app.js');
    
    $v8 = new V8Js();
    
    $v8->executeString('var process = { env: { VUE_ENV: "server", NODE_ENV: "production" }}; this.global = { process: process };');
    $v8->executeString($vue_source);
    $v8->executeString($renderer_source);
    $v8->executeString($app_source);
    ?>
    
    // app.js
    var vm = new Vue({
      template: `<div>{{ msg }}</div>`,
      data: {
        msg: 'hello'
      }
    })
    
    // exposed by vue-server-renderer/basic.js
    renderVueComponentToString(vm, (err, res) => {
      print(res)
    })
    

    v-on 修饰符

    键值 key 自动修饰符

    在 Vue v2.5 之前的版本中,如果要在 v-on 中使用没有内置别名的键盘键值,要么直接使用 keyCode 当修饰符(@keyup.13="foo"),要么需要使用 config.keyCodes 来为键值注册别名。

    在 v2.5 中,你可以直接使用合法的键值 key 值(参考 MDN 中的 KeyboardEvent.key )作为修饰符来串联使用它。如下:

    <input @keyup.page-down="onPageDown">
    

    上述例子中,事件处理函数只会在 $event.key === 'PageDown' 时被调用。

    注意:现有键值修饰符仍然可用。在 IE9 中,一些键值(.esc 和 方向键的 key )不是一致的值,如果要兼容 IE9,需要按 IE9 中内置的别名来处理。

    .exact 修饰符

    新增了一个 .exact 修饰符,该修饰符应该和其他系统修饰符(.ctrl, .alt, .shift and .meta)结合使用,可用用来区分一些强制多个修饰符结合按下才会触发事件处理函数。如下:

    <!-- 当 Alt 或 Shift 被按下也会触发处理函数 -->
    <button @click.ctrl="onClick">A</button>
    
    <!-- 只有当 Ctrl 被按下,才会触发处理函数 -->
    <button @click.ctrl.exact="onCtrlClick">A</button>
    

    简化 Scoped Slots 的使用

    之前,如果要在 template 标签上使用 scope 属性定义一个 scoped slot,可以像下面这样定义:

    <comp>
      <template scope="props">
        <div>{{ props.msg }}</div>
      </template>
    </comp>
    

    在 v2.5 中,scope 属性已被弃用(仍然可用,但是会爆出一个警告,就像本文文首的那样),我们使用 slot-scope 属性替代 scope 属性来表示一个 scoped slot,且 slot-scope 属性除了可以被用在 template 上,还可以用在标签元素和组件上。如下:

    <comp>
      <div slot-scope="props">
        {{ props.msg }}
      </div>
    </comp>
    

    注意:这次的调整,表示 slot-scope 已经是一个保留属性了,不能再被单独用在组件属性上了。

    Inject 新增了默认值选项

    本次调整中,Injections 可以作为可选配置,并且可以声明默认值。也可以用 from 来表示原属性。

    export default {
      inject: {
        foo: {
          from: 'bar',
          default: 'foo'
        }
      }
    }
    

    与属性类似,数组和对象的默认值需要使用一个工厂函数返回。

    export default {
      inject: {
        foo: {
          from: 'bar',
          default: () => [1, 2, 3]
        }
      }
    }
    

    (完)

    3 条回复    2017-10-17 12:36:05 +08:00
    lukunlin
        1
    lukunlin  
       2017-10-17 11:30:04 +08:00
    期待 vue 和阿里的 weex 的结合,让前端可以随时随地的跨平台
    corona
        2
    corona  
       2017-10-17 12:31:31 +08:00 via iPhone
    @lukunlin 不是说 weex 开发团队都快散了吗?我也只是听说
    noe132
        3
    noe132  
       2017-10-17 12:36:05 +08:00 via Android
    weex 现在貌似很尴尬,各种 bug,文档也很不完善
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1008 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 20:20 · PVG 04:20 · LAX 12:20 · JFK 15:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.