内容简介:我们接着上篇学习完我们先封装一个简单的组件,叫做代码如下:
我们接着上篇学习完 render
函数,下面我们来看下 Vue
中的函数式组件
这也是 Vue
进阶中一个重要的知识点,下面我们一起来学习下吧(我也不是很熟:smile:,有错误就请指正)
组件封装阶段
我们先封装一个简单的组件,叫做 list
代码如下:
<template> <ul> <li v-for="(item, index) in list" :key="`item_${index}`"></li> </ul> </template> <script> export default { name: 'List', props: { list: { type: Array, default: () => [] } } } </script> 复制代码
简单封装后,里面 li
里面的内容我们先不管!
我们再新建一个叫做 render
的组件
我们把刚刚的 list
组件引入到 render
组件里
<template> <div> <list :list="list"></list> </div> </template> <script> import List from '../component/list' export default { data () { return { list: [ { name: lili}, { name: Dreams} ] } }, components: { List } } </script> 复制代码
接下来,我们回到 list
组件里完善下 li
标签里面的内容
<li v-for="(item, index) in list" :key="`item_${index}`"> <span>{{ item.name }}</span> </li> 复制代码
这样我们就把刚刚 render
组件里传递进来的 list
数据给 list
组件使用并且渲染出了名字,这里我们用 span
标签包裹了,那么如果我们想更多的让用户个性化,比如用户想用什么标签包裹就用什么标签包裹,怎么做呢?
那么这里我们就可以使用 render
函数,然后让用户通过 render
函数自己去定义,来看下怎么写
这里我们回到 render
组件,把 render
函数通过 v-bind
传递到 list
里去
render组件的代码: <template> <div> <list :list="list" :render="renderFunc"></list> </div> </template> <script> import List from '../component/list' export default { data () { return { list: [ { name: lili}, { name: Dreams} ] } }, components: { List }, methods:{ renderFunc(h){ return h('i',{ style:{ color:'pink' } },'???') } } } </script> 复制代码
上面我们想使用i标签包裹,且字体颜色为粉红色,但这里我们 打问号的地方
他的值是多少呢?怎么来呢,因为 list
中他是通过 v-for
循环的,
那么我们想知道当前循环的这个值是多少,那么这里我们就要用到一个组件叫做: 函数式组件
函数式组件开始
那么接着上面,我们先创建一个 render-dom.js
代码如下
export default { functional: true,//必须这样写才是一个函数式组件 props: { name: String, renderFunc: Function }, render: (h, ctx) => { //??? } } 复制代码
那么有人会问了,函数式组件有什么作用?
一般而言,我们只给它传入一些数据,它不做任何响应式的操作,不监听传递给他的状态,它也没有生命周期,它只是一个接收参数的函数,当设置 functional
为 true
时,它是一个没有状态的组件,但是当你把他引入到其他vue组件中去用的时候, vue
会把它做相关处理,上面我们写了一个 render
函数, vue
会用 render
函数里的逻辑,把里面返回的节点做渲染!
接着我们回到 list
组件,在 props
里接收父组件(render组件)传递过来的 render
函数
props处新增代码: render: { type: Function, default: () => {} } 复制代码
接下来,我们把函数式组件再完善下
把刚刚 render
方法里的逻辑完善下就是
render: (h, ctx) => { return ctx.props.renderFunc(h,ctx.props.name) } 复制代码
返回的 render
其实就是用户传进来的那个 render
ctx
他其实就指代当前的上下文,那么我们就可以用 ctx
获取到属性里的 renderFunc
接下来继续到 list
组件里使用renderDom函数式组件
模板中新增: <li v-for="(item, index) in list" :key="`item_${index}`"> <span v-if="!render">{{ item.number }}</span> <render-dom v-else :render-func="render" :name="item.name"></render-dom> </li> script引入: import RenderDom from '../component/render-dom' components: { //注册组件 RenderDom }, 复制代码
这里逻辑就是如果用户传入了render,我们就是用传入的render渲染,否则默认span
接下来我们回到render组件里把刚刚的render函数完善下:
renderFunc(h,name){ return h('i',{ style:{ color:'pink' } },name) } 复制代码
那么这里的name其实就是函数式组件返回的name,所以这里我们直接使用name
那么这样我们就完成了可以让用户自己定义这个文字该怎么样展现!render配合函数式组件就是这么灵活!
那么大家应该也发现了,render加函数式组件其实非常繁琐!那么有没有什么东西可以简化呢? 其实是有的, 那就是JSX!
JSX
JSX是React最先提出的,那么后来Vue也做了相关支持!他的本质其实就是在js中写html标签和一些特定的语法,最终呢他会把jsx转换成render函数去渲染。
接下来我们回到render组件里把刚刚的render函数修改下:
之前template是这样的: <list :list="list" :render="renderFunc"></list> 之前js是这样的: renderFunc(h,name){ return h('i',{ style:{ color:'pink' } },name) } 修改之后的template: <list :list="list" :render="renderFunc" :style="{color:'red'}"></list> 修改之后的js: renderFunc(h,name){ return ( <i style={{color:'red'}}>{name}</i> ) } 复制代码
这里要注意了,在jsx中,变量要用花括号包起来!里面是一个对象,然后又有一个花括号.因为name也是变量,所以也需要使用花括号包起来!
这样就完成了和刚刚render函数一样的功能!
如果我们想给i标签绑定一个事件,我们应该怎么绑定?
methods:{ renderFunc(h,name){ return ( <i on-click={this.handleClick} style={{color:'red'}}>{name}</i> ) }, handleClick(event){ console.log(event) } } 复制代码
这里还要注意,绑定事件必须是 on-
开头
那么普通的渲染标签我们会了,那么如果渲染一个组件呢?
渲染组件
那么这里假设我们这里有一个组件CountTo(看过上上篇文章的小伙伴应该知道)组件
我们把他引入到render组件(看过上篇文章的小伙伴应该知道这个组件)中. 再写一遍!
我们这里需要修改之前的一些代码:
render组件中修改后的:(函数式组件和list里需要做一部分修改,我相信大家可以的,就不罗列相关代码了)
<template> <div> <list :list="list" :style="{color: 'red'}"></list> </div> </template> <script> import List from '_c/list' import CountTo from '_c/count-to' export default { data () { return { list: [ { number: 100 }, { number: 45 } ] } }, components: { List }, methods: { renderFunc (h, number) { return ( <CountTo nativeOn-click={this.handleClick} on-on-animation-end={this.handleEnd} endVal={number} style={{color: 'pink'}}></CountTo> ) }, handleClick (event) { // console.log(event) }, handleEnd () { // console.log('end!') } } } </script> 复制代码
我们如果是在render或者jsx里写的组件是不需要进行注册的!
那么这里我们也使用了JSX做了相同的事情。其实这里还可以使用作用域插槽做同样的事情,这篇文章我们主要讲JSX和函数式组件,所以就不再举插槽相关的代码哦,有兴趣的可以下去自己试试!
总结
本篇文章我们一起学习了render+函数式组件,最终我们完成了之前的需求,但过程还是比较繁琐的,结尾我们也提到了JSX的解决方案, 感兴趣的小伙伴可以关注我,大家一起学习vue中比较难理解的知识点哦!
各位大佬,如果发现文中的错误,请指正,我会及时修改!
感谢大佬们能在百忙中能阅读完这篇文章!
再次总结
相信大家看完这篇文章后再去看vue文档就不会觉得那么吃力了!大家共勉!
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 每日一题(开开森森学前端之Object系列)
- 每日一题(开开森森学前端之常见笔试题)
- 前端科普系列(三):CommonJS 不是前端却革命了前端
- 前端科普系列(三):CommonJS 不是前端却革命了前端
- 前端技术演进(三):前端安全
- 【前端优化】前端常见性能优化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Machine Learning
Kevin Murphy / The MIT Press / 2012-9-18 / USD 90.00
Today's Web-enabled deluge of electronic data calls for automated methods of data analysis. Machine learning provides these, developing methods that can automatically detect patterns in data and then ......一起来看看 《Machine Learning》 这本书的介绍吧!