Vue函數式組件 jsx語法


創建

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>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM