函数式组件思想与简单例子说明

单文件组件

  • 简单来说,单文件组件就是组件的行为、数据、结构等等统一放在一个文件里由Vue的构建系统识别并渲染的*.vue文件;
  • 随着vue cli 的更新迭代,任然使用new Vue的方式建立全局组件并在各个页面选择容器进行投放显然已经落伍了,单文件组件开发在大型项目中已经非常的普遍!请看下图:(这是官方文档里给出的单文件组件示例图)

函数式组件思想与简单例子说明_第1张图片

  • 或者说这样的结构
<template>
  <div>
    <h1>demoh1>
    <h1> {{name}} h1>
    <demoComp/>
  div>
template>
<script>
import demoComp from './view/democomp'
export default {
  name:'sub-menu',
  components:{demoComp},
  props: ['menuInfo'],
  data:{
    return:{
      name:'haha'
    }
  },
  methods:{
    hello(){
      console.log('hello')
    }
  },
  created(){
  }
}
script>
<style>
*{
  margin: 0;
  padding: 0;
}
style>

单文件递归的函数式组件

  • 注意点1:声明functional

单文件组件如此声明可以不用再js里增加functional:true属性值

单文件组件声明方式:

<template functional>
  <div>{{ props.foo }}div>
template>

旧声明方式:

Vue.component('smart-list', {
     //标记为函数式组件
     functional: true,
     //render函数
     render: function (createElement, context) {
         //规定组件的渲染规则
         function appropriateListComp() {
         }
         //生成模板
         return createElement(
             //模板标记为渲染规则函数返回值
     },
     props: {
        items: {
            type: Array,
            required: true
        },
        isOrdered: Boolean
    }
})
  • 在自己的组件里复用自己:如果是普通组件,需要设置name属性,name的值就是该普通组件的名称,使用该普通组件需要这个名称
<template>
	<democom/>
<template/>
export default{
	name:'democom'
}

如果是函数式组件就不需要另外在name属性中声明了!

  • 注意点2:组件的数据传递

由于函数式组件都是在渲染函数上下文中进行求值,所以,不能通过data,不能通过this对数据进行访问,官方文档也做了详细的阐述:

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

  • props:提供所有 prop 的对象
  • children: VNode 子节点的数组
  • slots: 返回所有插槽的对象的函数
  • scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽以及函数形式的普通插槽的对象。
  • data:传递给组件的数据对象,作为 createElement 的第二个参数传入组件
  • parent:对父组件的引用
  • listeners: (2.3.0+) 一个包含了所有在父组件上注册的事件侦听器的对象。这只是一个指向 data.on 的别名。
  • injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。
  • 在添加 functional: true 之后,锚点标题组件的 render 函数之间简单更新增加 context 参数,this.$slots.default 更新为 context.children,之后this.level 更新为 context.props.level

因为函数式组件只是一个函数,所以渲染开销也低很多。然而,对持久化实例的缺乏也意味着函数式组件不会出现在 Vue devtools 的组件树里。

以我的一个例子来讲:例子来源于ant-design-vue的导航组件,很多大型单页项目里,导航会跟着用户的操作进行动态的变化,如果冗杂的手动书写导航菜单并用显隐控制显然是开销巨大的!那么根据设定好的数据进行递归渲染明显是一个可行的好办法!
组件地址

忽略我是用的pug语法,使用了一些事件方法,我们看重点:

首先,a-menu是ant的导航组件容器,子组件在a-menu下不能用其他盒子包裹,子组件包含两种:普通导航a-menu-item和折叠导航 a-sub-menu,我这里选择将折叠作为依据进行判断然后重复递归渲染:

.content
      .leftnav
        a-menu(
          :defaultSelectedKeys="['1']"
          :defaultOpenKeys="['2']"
          :mode="'inline'"
          :inlineCollapsed="collapsed"
          @click="handleClick")
          template(v-for="item in navigations")
            a-menu-item(
              v-if="!item.children"
              :key="item.key")
              a-icon(type="pie-chart")
              span {{item.title}}
            sub-menu(
              v-else
              :menu-info="item"
              :key="item.key")

引入自定义函数式组件:
import SubMenu from '../components/subMenu'

components:{
	cub-menu:SubMenu
}
<template lang='pug' functional>
  a-sub-menu(
    :key="props.menuInfo.key")
    span(slot="title")
      a-icon(type="mail")
      span {{ props.menuInfo.title }}
    template(v-for="item in props.menuInfo.children")
      a-menu-item(
        v-if="!item.children"
        :key="item.key")
        a-icon(type="pie-chart")
        span {{ item.title }}
      sub-menu(
        v-else
        :key="item.key"
        :menu-info="item")
</template>
<script>
export default {
  // name:'sub-menu',
	props: ['menuInfo'],//遵守规范,html不适用大写字母,驼峰命名会被解析成短横线
}
</script>

看一下我的数据:


navigations: [{
	key: '1',
	title: 'Option 1',
},{
	key: '2',
	title: 'Navigation 2',
	children: [{
		key: '2.1',
		title: 'Navigation 3',
		children: [
			{ key: '2.1.1',
				title: 'Option 2.1.1',
			},
		]},
	],
},{
	key: '3',
	title: 'Navigation 3',
	children: [{
		key: '3.1',
		title: 'Navigation 4',
		children: [
			{ key: '3.1.1',
				title: 'Option 3.1.1',
			},
		],
	}],
}],

渲染出来的效果:
函数式组件思想与简单例子说明_第2张图片
父组件通过v-bind:menu-info:"item"想子组件传递了含有children的数据,子组件通过props接受,并赋值到menuInfo中,数据通过props.menuInfo调用,注意的是,vue的数据传递模板里使用短横线({{ props.menu-info.title }})是不行的,所以在props里使用menuInfo命名!虽然:menuInfo="item"也不会报错,但是并不符合html的规范,不建议在html的标签里使用驼峰命名(组件会被js先解析之后再添加到DOM里渲染,故组件名是可以使用驼峰命名的)!

你可能感兴趣的:(Vue.js,前端学习笔记)