Vue.js 实用技巧(二)
2017-03-08 21:02
411 查看
转载自:https://zhuanlan.zhihu.com/p/25623356
观众老爷们好,如果你看过上一篇文章就会知道,我们这个系列是介绍 Vue.js 实践中的一些技巧,合理的运用还是能提升一些开发效率的。今天介绍 jsx 的特殊用法和 Vue.js 的新功能 —— $props。
调用 notification 服务,显示一段自定义的内容。这段代码并没有写在 render 里,但是其实我们也能写成 jsx,例如:
使用
babel-plugin-transform-vue-jsx 插件,这段代码可以正常运行。原理其实很简单,vue-jsx 插件文档里提到 render(h) 中的 h 其实就是
this.$createElement,那么我们只需要在使用 jsx 的方法中声明一下 h 就完成了。如果有用到 eslint,可以加上
// eslint-disable-line 忽略提示:
实际上在最新发布的
babel-plugin-transform-vue-jsx 3.4.0 里已经不在需要手动声明 h 变量,现在就可以愉快的写 jsx 在组件里的任何地方。
$props。文档只是很简洁的介绍了是什么但并没有解释有什么用,那下面我给大家分享下哪些情况会需要这个属性。
但是如果需要支持其他原生属性就需要继续写模板内容:
如果还要设置 type,或者是要同时支持 textarea,那么重复的代码量还是很可怕的。但是换个思路,直接用 jsx 写的话或许会轻松一些:
在 Vue 的 vnode 中,原生属性是定义在 data.attrs 中,所以上面 input 部分会被编译成:
这样就完成了原生属性的传递,同理如果需要通过 type 设置 textarea,只需要加个判断设置 tag 就好了。
目前为止我们还是需要定义一个 attrs 对象,但是所需要的属性其实都已经定义在了 props 中,那么能直接从 props 里拿到值岂不是更好?我们可以简单的写一个 polyfill 完成这件事。(实际上 Vue 2.2 中不需要你引入 polyfill,默认已经支持)
原理很简单,从 vm.$options.props 遍历 key 后从 vm 中取值,现在我们就可以直接从 vm.$props 拿到所有 props 的值了。那么我们的代码就可以改成这样:
如果你留意过 Vue 文档介绍
v-bind 是可以传对象 的话,那我们的代码用 Vue 模板写的话就更简单了:
例如封装一个带校验功能的 input 组件,代码可能是这样:
关键就是如何传 XInput 的 props。其实只需要在当前组件的 props 中把 Xinput 的 props 复制一遍后,用 v-bind 就完成了。
或者用 Object.assign 也可以实现:
以上就是 $props 的基本用法,如果你有其他看法或用法欢迎留言分享。好了这个系列的分享告一段落,所有例子的代码我都放在了
vue-tricks 仓库里。下次再见!
Vue.js
$props · Issue #4571 · vuejs/vue
vuejs/babel-plugin-transform-vue-jsx
QingWei-Li/vue-tricks
观众老爷们好,如果你看过上一篇文章就会知道,我们这个系列是介绍 Vue.js 实践中的一些技巧,合理的运用还是能提升一些开发效率的。今天介绍 jsx 的特殊用法和 Vue.js 的新功能 —— $props。
技巧一:任何地方都能写 jsx
写过 Vue jsx 的都知道,通常我们需要将 jsx 写在 render(h) {} 中。但是有些情况下我们想在其他方法里也能写 jsx,例如上篇文章的一个 Element 组件的例子。const h = this.$createElement this.$notify({ title: 'GitHub', message: h('div', [ h('p', '[GitHub] Subscribed to ElemeFE/element notifications'), h('el-button', {}, '已读') ]) })
调用 notification 服务,显示一段自定义的内容。这段代码并没有写在 render 里,但是其实我们也能写成 jsx,例如:
{ methods: { showNotify() { const h = this.$createElement this.$notify({ title: 'GitHub', message: ( <div> <p>[GitHub] Subscribed to ElemeFE/element notification</p> <el-button>已读<el-button> <div>) }) } } }
使用
babel-plugin-transform-vue-jsx 插件,这段代码可以正常运行。原理其实很简单,vue-jsx 插件文档里提到 render(h) 中的 h 其实就是
this.$createElement,那么我们只需要在使用 jsx 的方法中声明一下 h 就完成了。如果有用到 eslint,可以加上
// eslint-disable-line 忽略提示:
const h = this.$createElement // eslint-disable-line
实际上在最新发布的
babel-plugin-transform-vue-jsx 3.4.0 里已经不在需要手动声明 h 变量,现在就可以愉快的写 jsx 在组件里的任何地方。
技巧二:$props 的使用姿势
Vue.js 2.2 中加入了一个新特性 ——$props。文档只是很简洁的介绍了是什么但并没有解释有什么用,那下面我给大家分享下哪些情况会需要这个属性。
1. 继承原生属性
当开发表单组件时,不得不解决的问题是继承原生组件的各种属性。例如封装一个 input 组件,要有原生的 placeholder 属性,那么我们的代码可能是这样:<template> <div> <label>{{ label }}</label> <input @input="$emit('input', $event.target.value)" :value="value" :placeholder="placeholder"> </div> </template> <script> export default { props: ['value', 'placeholder', 'label'] } </script>
但是如果需要支持其他原生属性就需要继续写模板内容:
<template> <div> <label>{{ label }}</label> <input @input="$emit('input', $event.target.value)" :value="value" :placeholder="placeholder" :maxlength="maxlength" :minlength="minlength" :name="name" :form="form" :value="value" :disabled="disabled" :readonly="readonly" :autofocus="autofocus"> </div> </template> <script> export default { props: ['label', 'placeholder', 'maxlength', 'minlength', 'name', 'form', 'value', 'disabled', 'readonly', 'autofocus'] } </script>
如果还要设置 type,或者是要同时支持 textarea,那么重复的代码量还是很可怕的。但是换个思路,直接用 jsx 写的话或许会轻松一些:
export default { props: ['label', 'type', 'placeholder', 'maxlength', 'minlength', 'name', 'form', 'value', 'disabled', 'readonly', 'autofocus'], render(h) { const attrs = { placeholder: this.placeholder, type: this.type // ... } return ( <div> <label>{ this.label }</label> <input { ...{ attrs } } /> </div> ) } }
在 Vue 的 vnode 中,原生属性是定义在 data.attrs 中,所以上面 input 部分会被编译成:
h('input', { attrs: attrs })
这样就完成了原生属性的传递,同理如果需要通过 type 设置 textarea,只需要加个判断设置 tag 就好了。
h(this.type === 'textarea' ? 'textarea' : 'input', { attrs })
目前为止我们还是需要定义一个 attrs 对象,但是所需要的属性其实都已经定义在了 props 中,那么能直接从 props 里拿到值岂不是更好?我们可以简单的写一个 polyfill 完成这件事。(实际上 Vue 2.2 中不需要你引入 polyfill,默认已经支持)
import Vue from 'vue' Object.defineProperty(Vue.prototype, '$props', { get () { var result = {} for (var key in this.$options.props) { result[key] = this[key] } return result } })
原理很简单,从 vm.$options.props 遍历 key 后从 vm 中取值,现在我们就可以直接从 vm.$props 拿到所有 props 的值了。那么我们的代码就可以改成这样:
render(h) { return ( <div> <label>{ this.label }</label> <input { ...{ attrs: this.$props } } /> </div> ) }
如果你留意过 Vue 文档介绍
v-bind 是可以传对象 的话,那我们的代码用 Vue 模板写的话就更简单了:
<template> <div> <label>{{ label }}</label> <input v-bind="$props"> </div> </template>
2. 继承自定义组件的属性
$props 的功能远不止于此。如果你需要基于上面的 input 组件封装成另一个组件时,那么我们要如何继承它的属性?例如封装一个带校验功能的 input 组件,代码可能是这样:
<template> <div> <XInput /> <div v-show="message && show-hit" class="hit">{{ message }}</div> </div> </template> <script> import XInput from './input.vue' export default { components: { XInput }, props: { showHit: Boolean }, data () { return { message: '错误提示' } } } </script>
关键就是如何传 XInput 的 props。其实只需要在当前组件的 props 中把 Xinput 的 props 复制一遍后,用 v-bind 就完成了。
<template> <div> <XInput v-bind="$props" /> <div v-show="message && show-hit" class="hit">{{ message }}</div> </div> </template> <script> import XInput from './input.vue' export default { components: { XInput }, props: { showHit: Boolean, ...XInput.props }, data () { return { message: '错误提示' } } } </script>
或者用 Object.assign 也可以实现:
{ props: Object.assign({ showHit: Boolean }, XInput.props) }
以上就是 $props 的基本用法,如果你有其他看法或用法欢迎留言分享。好了这个系列的分享告一段落,所有例子的代码我都放在了
vue-tricks 仓库里。下次再见!
参考链接
vuejs/babel-plugin-transform-vue-jsxVue.js
$props · Issue #4571 · vuejs/vue
vuejs/babel-plugin-transform-vue-jsx
QingWei-Li/vue-tricks
相关文章推荐
- Vue.js 实用技巧(二)
- vue.js项目中实用的小技巧汇总
- Struts中的一些实用技巧..JS定时跳,隐藏,单选
- js实用技巧
- JS:超实用的JavaScript技巧及最佳实践(下)
- JavaScript学习总结(8)——JS实用技巧总结
- Node.js静态文件服务器实战(接触nodejs开发中比较实用的部分技巧,获益匪浅)
- [JS代码]JavaScript实用的一些技巧
- 一些实用的js技巧
- js的一些实用技巧
- js实现在页面上弹出蒙板技巧简单实用
- JavaScript学习总结(8)——JS实用技巧总结
- JS框架的jQuery技巧实用大全
- 实用技巧:js图片等比缩放
- 实用技巧:js图片等比缩放
- js 处理URL实用技巧
- js 处理URL实用技巧
- 五段实用的js高级技巧
- 实用技巧:在JS应用中定义上下文根目录变量
- Js返回上一页,刷新页面,定时刷新,改变地址栏 等常用实用技巧