开开森森学前端之函数式组件和JSX

栏目: 编程语言 · 发布时间: 5年前

内容简介:我们接着上篇学习完我们先封装一个简单的组件,叫做代码如下:

我们接着上篇学习完 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) => {
    //???
  }
}
复制代码

那么有人会问了,函数式组件有什么作用?

一般而言,我们只给它传入一些数据,它不做任何响应式的操作,不监听传递给他的状态,它也没有生命周期,它只是一个接收参数的函数,当设置 functionaltrue 时,它是一个没有状态的组件,但是当你把他引入到其他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文档就不会觉得那么吃力了!大家共勉!


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Machine Learning

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》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

SHA 加密
SHA 加密

SHA 加密工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具