Vue学习笔记进阶篇之函数化组件解析


Posted in Javascript onJuly 21, 2017

这两天学习了Vue.js 感觉函数化组件这个地方知识点挺多的,而且很重要,所以,今天添加一点小笔记

介绍

之前创建的锚点标题组件是比较简单,没有管理或者监听任何传递给他的状态,也没有生命周期方法。它只是一个接收参数的函数。

在这个例子中,我们标记组件为 functional, 这意味它是无状态(没有 data),无实例(没有 this 上下文)。

一个 函数化组件 就像这样:

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

组件需要的一切都是通过上下文传递,包括:

  1. props: 提供props 的对象
  2. children: VNode 子节点的数组
  3. slots: slots 对象
  4. data: 传递给组件的 data 对象
  5. parent: 对父组件的引用
  6. listeners: (2.3.0+) 一个包含了组件上所注册的 v-on 侦听器的对象。这只是一个指向 data.on 的别名。
  7. injections: (2.3.0+) 如果使用了 inject 选项, 则该对象包含了应当被注入的属性。

在添加 functional: true 之后,锚点标题组件的 render 函数之间简单更新增加context参数,this.$slots.default 更新为 context.children,之后this.level 更新为 context.props.level。

因为函数化组件只是一个函数,所以渲染开销也低很多。另外,这也意味着函数化组件不会出现在 VueJS Chrome 开发者工具的组件树里。

在作为包装组件时它们也同样非常有用,比如,当你需要做这些时:

程序化地在多个组件中选择一个

在将 children, props, data 传递给子组件之前操作它们。

下面是一个依赖传入 props 的值的smart-list组件例子,它能代表更多具体的组件:

var EmptyList = { /* ... */ }
var TableList = { /* ... */ }
var OrderedList = { /* ... */ }
var UnorderedList = { /* ... */ }
Vue.component('smart-list', {
 functional: true,
 render: function (createElement, context) {
  function appropriateListComponent () {
   var items = context.props.items
   if (items.length === 0)      return EmptyList
   if (typeof items[0] === 'object') return TableList
   if (context.props.isOrdered)   return OrderedList
   return UnorderedList
  }
  return createElement(
   appropriateListComponent(),
   context.data,
   context.children
  )
 },
 props: {
  items: {
   type: Array,
   required: true
  },
  isOrdered: Boolean
 }
})

slots()和children对比

你可能想知道为什么同时需要 slots()childrenslots().default 不是和 children 类似的吗?在一些场景中,是这样,但是如果是函数式组件和下面这样的 children 呢?

<my-functional-component>
 <p slot="foo">
  first
 </p>
 <p>second</p>
</my-functional-component>

对于这个组件,children 会给你两个段落标签,而 slots().default 只会传递第二个匿名段落标签,slots().foo 会传递第一个具名段落标签。同时拥有 children 和 slots() ,因此你可以选择让组件通过 slot() 系统分发或者简单的通过 children 接收,让其他组件去处理。

示例

渐进过渡

之前的Vue学习笔记进阶篇——列表过渡及其他中可复用的过渡提到用函数组件实现合适,下面就用函数化组件来实现那个渐进过渡

<div id="app5">
  <input v-model="query">
  <my-transition :query="query" :list="list">
    <li v-for="(item, index) in computedList"
      :key="item.msg"
      :data-index="index">
      {{item.msg}}
    </li>
  </my-transition>
</div>
  Vue.component('my-transition', {
    functional:true,
    render:function (h, ctx) {
      var data = {
        props:{
          tag:'ul',
          css:false
        },
        on:{
          beforeEnter:function (el) {
            el.style.opacity = 0
            el.style.height = 0
          },
          enter:function (el, done) {
            var delay = el.dataset.index * 150
            setTimeout(function () {
              Velocity(el, {opacity:1, height:'1.6em'},{complete:done})
            }, delay)
          },
          leave:function (el, done) {
            var delay = el.dataset.index * 150
            setTimeout(function () {
              Velocity(el, {opacity:0, height:0}, {complete:done})
            }, delay)
          }
        }
      }
      return h('transition-group', data, ctx.children)
    },
    props:['query', 'list']
  })

  var app5 = new Vue({
    el:'#app5',
    data:{
      query:'',
      list:[
        {msg:'Bruce Lee'},
        {msg:'Jackie Chan'},
        {msg:'Chuck Norris'},
        {msg:'Jet Li'},
        {msg:'Kung Furry'},
        {msg:'Chain Zhang'},
        {msg:'Iris Zhao'},
      ]
    },
    computed:{
      computedList:function () {
        var vm = this
        return this.list.filter(function (item) {
          return item.msg.toLowerCase().indexOf(vm.query.toLowerCase()) !== -1
        })
      }
    },
  })

运行结果:

Vue学习笔记进阶篇之函数化组件解析

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
一起来写段JS drag拖动代码
Dec 09 Javascript
js判断是否为数组的函数: isArray()
Oct 30 Javascript
Javascript执行效率全面总结
Nov 04 Javascript
jQuery圆形统计图开发实例
Jan 04 Javascript
JS JQUERY实现滚动条自动滚到底的方法
Jan 09 Javascript
在JavaScript中操作时间之setYear()方法的使用
Jun 12 Javascript
js监听input输入框值的实时变化实例
Jan 26 Javascript
使用Vue自定义数字键盘组件(体验度极好)
Dec 19 Javascript
JS控制鼠标拒绝点击某一按钮的实例
Dec 29 Javascript
vue中使用微信公众号js-sdk踩坑记录
Mar 29 Javascript
layer弹出层倒计时关闭的实现方法
Sep 27 Javascript
在vue中使用Base64转码的案例
Aug 07 Javascript
用javascript获取任意颜色的更亮或更暗颜色值示例代码
Jul 21 #Javascript
基于JavaScript实现数码时钟效果
Mar 30 #Javascript
bootstrap多层模态框滚动条消失的问题
Jul 21 #Javascript
基于JavaScript实现无缝滚动效果
Jul 21 #Javascript
基于JavaScript实现选项卡效果
Jul 21 #Javascript
基于JavaScript实现弹幕特效
Aug 27 #Javascript
js实现水平滚动菜单导航
Jul 21 #Javascript
You might like
基于PHP+jQuery+MySql实现红蓝(顶踩)投票代码
2015/08/25 PHP
php版微信开发之接收消息,自动判断及回复相应消息的方法
2016/09/23 PHP
利用PHP生成静态html页面的原理
2016/09/30 PHP
深入了解PHP中的Array数组和foreach
2016/11/06 PHP
读jQuery之四(优雅的迭代)
2011/06/20 Javascript
dotopAlert 提示用户需安装播放器的代码
2012/09/17 Javascript
jQuery页面图片伴随滚动条逐渐显示的小例子
2013/03/21 Javascript
拥有一个属于自己的javascript表单验证插件
2016/03/24 Javascript
XMLHttpRequest Level 2 使用指南
2016/08/26 Javascript
原生JS实现九宫格抽奖效果
2017/04/01 Javascript
Vue2.0基于vue-cli+webpack父子组件通信(实例讲解)
2017/09/14 Javascript
inner join 内联与left join 左联的实例代码
2017/09/18 Javascript
vue中的provide/inject的学习使用
2018/05/09 Javascript
webpack4 处理SCSS的方法示例
2018/09/03 Javascript
Bootstrap 时间日历插件bootstrap-datetimepicker配置与应用小结
2019/05/28 Javascript
vue.js watch经常失效的场景与解决方案
2021/01/07 Vue.js
[38:23]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第一场
2014/05/24 DOTA
Python3.2中Print函数用法实例详解
2015/05/19 Python
python实现可以断点续传和并发的ftp程序
2016/09/13 Python
Python中函数eval和ast.literal_eval的区别详解
2017/08/10 Python
详解Pytorch 使用Pytorch拟合多项式(多项式回归)
2018/05/24 Python
Python模块的加载讲解
2019/01/15 Python
Python获取Redis所有Key以及内容的方法
2019/02/19 Python
Python实现账号密码输错三次即锁定功能简单示例
2019/03/29 Python
python抖音表白程序源代码
2019/04/07 Python
python生成特定分布数的实例
2019/12/05 Python
TensorBoard 计算图的查看方式
2020/02/15 Python
HTML5拖放效果的实现代码
2016/11/17 HTML / CSS
美国运动鞋和服装网上商店:YCMC
2018/09/15 全球购物
Linux常见面试题
2013/03/18 面试题
团日活动策划书
2014/02/01 职场文书
学习雷锋精神演讲稿
2014/05/10 职场文书
辞职信怎么写
2015/02/27 职场文书
2015年政风行风工作总结
2015/04/21 职场文书
公司员工手册范本
2015/05/14 职场文书
婚礼家长致辞
2015/07/27 职场文书