创建

index.js

import "./index.less"   //{0}
export default {        
    name: 'testComp',
    props: {
        title:""
    },
    data() {
        return {
            name:'test'
        }
    },
    computed:{},
    created() {},
    ...,            //{1}
    methods: {
    	test(){
            console.log("testFn")
        }
	},
    render() {      //{2} 
        console.log(this.title);
        console.log(this.name);
        this.test();
        return (
            <div>
                函数式组件
            </div>
        )
    },
} 

{0} :这个是引入的css

{1}:这里省略掉其他的内容

{2}:只里有一个render函数,这个函数类似普通组件的template,但是比template做的事多

页面效果:

总结:

其实函数式组件和普通组件没有很大的区别,主要通过render函数返回页面显示内容,而render函数是可以通过this调用到所有内容的

index.less

div{
    color: red;
}

app.vue

<test-comp title="测试组件"></test-comp>

基础开发

还是和以前组件一样正常开发就是了,只是说HTML部分通过函数返回,下面编写几种常用的返回方式

简单函数返回

methods上添加方法simpleReturn
simpleReturn() {
  return (<span class='test'>这是一种简单返回</span>)
}
render函数上调用该方法
render() {
        return (
            <div>
                函数式组件{this.simpleReturn()}
            </div>
        )
},
index.less上添加样式test
div{
    color: red;
}
.test{
    color: blue;
}
展示效果

基本语法: 这里你可以看到我们不再使用template上的{{}},而是{}表示js相关代码

还有这里用的还是class,在react上是className,不要混了哦!

if判断返回

methods上添加方法ifReturn
ifReturn(bol) {
    let content = null;
    if(bol){
        content = <p class='test'>我是true的返回</p>;
    }else{
        content = <p class='test'>我是false的返回</p>;
    }
    return content
}
render函数上调用该方法
render() {
        return (
            <div>
                函数式组件{this.simpleReturn()}
                {this.ifReturn(false)}
                {this.ifReturn(true)}
            </div>
        )
},
展示效果

for循环返回

methods上添加方法forReturn
forReturn(arr) { 
   let content = [];
   for (let index = 0; index < arr.length; index++) {
      content.push(<li>{arr[index]} : {index}</li>)
   }
   return content
}
render函数上调用该方法
render() {
        return (
            <div>
               // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
                 <ul>
                {this.forReturn(["测试","哈哈","嘻嘻","哇哇"])}
                </ul>
                <ul>
                    {["测试","哈哈","嘻嘻","哇哇"].map((item,index) => <li>{index}:{item}</li>)}
                </ul>
            </div>
        )
},
展示效果

这里有两种方式实现循环,其实基本一样,但是代码分离可能对后面的维护更方便,注意这里使用的是数组的map方法,不知道的可以查查资料

属性绑定(中阶)

如果说这个不能绑定属性,那再怎么说都不香了,其实我们看到这里的所有js部分都是由{}完成的,所以我们大胆猜测一下,属性绑定是不是也是这样呢???

render函数

render() {
    return (
        <div>
           // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
            <input v-model={name}/>
        </div>
    )
},

效果

咦,test没上去,这个绑定咋不灵了,难道我们猜错了,不会吧,不会吧,不会真的错了吧!!!

思考:我们在哪写的代码???

回答:render函数呀!!!

注意:对,render函数,你以前在函数中使用是直接用的name属性的吗???

是不是明白了什么,以前能在template上使用不需要this,但是现在要了!!!

所以最后修改为

render() {
    return (
        <div>
           // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
            <input  v-model={this.name}/>
            <input  value={this.name}/>
        </div>
    )
},

效果:

值绑定上去了,而且是响应式的

总结一下:这里绑定是要用{},不再是以前的v-bind(:),还要注意一定要this

事件绑定(中阶)

这给我一种原生的差不多,感觉没有vue的指令啥的,那么是否绑定事件也是和原生的差不多呢???试试看!!!

render函数

render() {
    return (
        <div>
            // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
            <ul onclick={this.inputInfo} >
                {["测试","哈哈","嘻嘻","哇哇"].map((item,index) => <li>{index}:{item}</li>)}
            </ul>
            <input onInput={this.inputInfo} v-model={this.name}/>
        </div>
    )
},

我在ul上绑定了一个onclick事件,然后在input上绑定了一个onInput事件,然后测试一下,发现都成功了

有没有发现我上面的truefalse变成了假的真实,我清一下缓存刷新就好了,我想不会吧,不会吧,这玩意还有缓存???这也太不稳定了吧!!!当我把所有笔记写完的时候我突然意识到了,咦,这个可能不是缓存原因!!!哈哈哈,所以还是要三思而后行呀!!!嘻嘻嘻

总结

是不是都会了呢!!!其实函数式组件也就这么简单,但是其实我还有没有告诉你的,嘻嘻

复杂绑定(中高)

这个复杂可以是你想的那个复杂,也可以是看上去就很复杂的样子,暂时只了解了两个,后续有用到在补充

v-bind="$attrs"

这个你是不是很熟悉呢!!!简单的说就是,你在父组件上写定义的变量,只要你子组件上不接收,然后你的孙子组件上添加上v-bind="$attrs"这段,那么这个就可以继续传递下去,那这个有什么用呢!!!那么在这里怎么用呢???

app.vue
<test-comp  type="primary"  plain  title="测试组件"></test-comp>

render函数

render() {
     console.log(this.$attrs)
    return (
        <div>
            // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
            <el-button {...{props:this.$attrs}}>主要按钮</el-button>

            
            <el-button {...{attrs:this.$attrs}}>主要按钮</el-button> 
        </div>
    )
},
效果

可以看到这个属性已经继承下去了,是不是很棒,但是这个写法就有点小复杂了

{...{props:this.$attrs}}:最外层{}表示绑定,然后内部使用展开对象...,然后就是一个对象,属性props(其实这就是参数,也可以使用attrs),然后将$attrs里保存的是没有接收的参数(真的是没有接收的吗?我试试),这里的title是接收了的,但是我新加的两个属性是没有的,结果都在这里,就说明真的是这样的

多属性一次绑定

咦!这里咋是一个对象呢?不是a属性 = b,而且这里的翻译一下不就是{...{props:{plain:"",type:"primary"}}},那么我要是想在这里绑定一些其他属性呢???我是不是可以浑水摸鱼一波,和这个this.$attrs一起混进去呢?

app.vue
<test-comp  plain  title="测试组件"></test-comp>

render函数

render() {
     console.log(this.$attrs)
    return (
        <div>
            // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
            <el-button {...{props:this.$attrs}}>主要按钮</el-button>
        </div>
    )
},
效果

可以看到,我们父组件绑定的属性减少,但是样式还是一样没变,因为我们在子组件给他加上去了,所以你想加多少就加多少,是不是很爽

但是这样说好像没什么用,其实这里只是一个参数外放的思路而已,也许对你来说没意思,或者说不需要我提示

v-on="$listeners"

了解一下v-on="$listeners",这个和v-bind="$attrs" 差不多,只是一个传递数据,一个传递事件,这样你就可以在这个父组件的子孙后代....中直接触发父组件的方法

我们上面的看到 v-bind="$attrs" 变成了 {...{attrs: this.$attrs}} 这样.咦,这里没有接收的数据是不是都是存在了$attrs里,而v-on="$listeners"代表的则是事件传递,那么是不是所有的事件都存在了$listeners了呢???

<el-table {...{ attrs: this.$attrs,on: this.$listeners }} class="table-info-detail">
    <el-table-column  prop='test' label='测试' ></el-table-column> 
</el-table>

等下次我会写一个完成的函数式组件出来,是一个表格组件,如果你做管理后台,一天到晚的复制粘贴代码,我觉得你可以抱住试试的心态关注一下我!!!不过我的组件是基于element-ui的,还有技术有限,如果没有达到你的期望,还请见谅!!!

插槽数据的获取

看上面两个,其实我们也能大致猜到,这里的插槽也在这个位置,只是形式有点不同,让我们来瞧一瞧

<el-table-column 
  prop="solt"
  label="插槽"
  {...{ 
      scopedSlots: {
          default: ({ row, $index }) => {
              
          },
      },
}}></el-table-column>

上面的展示的为el-table-column的默认插槽,其他插槽不需要多解释了吧!!!

咦,那添加插槽呢???

render

render() {
    console.log(this.$attrs)
    let propsObj = Object.assign({},this.$attrs,{type:"primary"});
    return (
        <div>
            // 因为关注点问题,我省略了前面的代码!!! 后面贴全部
            {this.$scopedSlots.default({
                index: 0,
            })}
        </div>
    )
},
    

app.vue

<test-comp boder @cell-click="cellClick" :data="[{test:'4444545'},{test:'4444545'}]">
     <template slot-scope="{index}">
         <span style="color:red">插槽{{index}}</span>
     </template>
</test-comp>

总结

到此就结束了,上面的知识点知道后,基本上是可以写一个很不错的组件出来的, 学习的过程总是这么的开心,哈哈哈,相信明天的自己会更强吧!!!

所有代码

import "./index.less"

export default {
    name: 'testComp',
    props: {
        title: ""
    },
    data() {
        return {
            name: "test"
        }
    },
    computed: {},
    created() {
    },
    methods: {
        test() {
            console.log("testFn")
        },
        simpleReturn() {
            return (<span class='test'>
                这是一种简单返回
            </span>)
        },
        ifReturn(bol) {
            let content = null;
            if(bol){
                content = <p class='test'>我是true的返回</p>;
            }else{
                content = <p class='test'>我是false的返回</p>;
            }
            return content
        },
        forReturn(arr) {
            let content = [];
            for (let index = 0; index < arr.length; index++) {
                content.push(<li>{arr[index]} : {index}</li>)
            }
            return content
        },
        inputInfo(){
            console.log(this.name)
        }
    },
    render() {
        console.log(this.$attrs)
        let propsObj = Object.assign({},this.$attrs,{type:"primary"});
        return (
            <div>
                函数式组件{this.simpleReturn()}
                {this.ifReturn(false)}
                {this.ifReturn(true)}
                <ul>
                    {this.forReturn(["测试","哈哈","嘻嘻","哇哇"])}
                </ul>
                <ul onclick={this.inputInfo} >
                    {["测试","哈哈","嘻嘻","哇哇"].map((item,index) => <li>{index}:{item}</li>)}
                </ul>
                <input onInput={this.inputInfo} v-model={this.name}/>
                <el-button {...{props:propsObj}}>
                </el-button>
                <el-table {...{attrs: this.$attrs, on: this.$listeners}} className="table-info-detail">
                    <el-table-column prop='test' label='测试'></el-table-column>
                </el-table>
                {this.$scopedSlots.default({
                    index: 0,
                })}
            </div>
        )
    },
}

index.less

div{
    color: red;
}
.test{
    color: blue;
}

app.vue

<template>
    <div id="app"> 
        <test-comp boder @cell-click="cellClick" :data="[{test:'4444545'},{test:'4444545'}]">
            <template slot-scope="{index}">
                <span style="color:red">插槽{{index}}</span>
            </template>
        </test-comp>
    </div>
</template>

<script> 
    import testComp from './components/testComp' 

    export default {
        name: 'App',
        components: {
           testComp
        },
        data() {
            return { 
            }
        },
        methods: {
            cellClick(row, column, cell, event){
                console.log(row, column, cell, event)
            }, 
        }
    }
</script>

<style lang="less">

</style>

posted on 2020-11-25 00:39  人生之外的路途  阅读(861)  评论(0编辑  收藏  举报