Vue2之virtual dom,render函數化組件

Vue.js提供了一個functional的布爾值選項亿傅,設置為true可以使組件無狀態(tài)和無實例老玛,也就是沒有data和this上下文淤年。這樣用render函數返回虛擬節(jié)點可以更容易渲染,因為函數化組件只是一個函數蜡豹,渲染開銷要小很多麸粮。
使用函數化組件時,Render函數提供了第二個參數context來提供臨時上下文镜廉。組件需要的data,props,slots,children,parent都是通過這個上下文來傳遞的豹休,比如this.level要改寫成context.props.level,this.$slolts.default改寫成context.children。

下面示例用函數化組件展示了一個根據數據智能選擇不同組件的場景:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
    <smart-item :data="data"></smart-item>
    <button @click="change('img')">切換為圖片組件</button>
    <button @click="change('video')">切換為視頻組件</button>
    <button @click="change('text')">切換為文本組件</button>
</div>
<script>
    // 圖片組件選項
    var ImgItem = {
        props:['data'],
        render:function (createElement) {
            return createElement('div',[
                createElement('p','圖片組件'),
                createElement('img',{
                    attrs:{
                        src: this.data.url
                    }
                })
            ]);
        }
    }
    // 視頻組件選項
    var VideoItem = {
        props:['data'],
        render:function (createElement) {
            return createElement('div',[
                createElement('p','視頻組件'),
                createElement('video',{
                    attrs:{
                        src: this.data.url,
                        controls: 'controls',
                        autoplay: 'autoplay'
                    }
                })
            ]);
        }
    }
    // 純文本組件選項
    var TextItem = {
        props:['data'],
        render:function (createElement) {
            return createElement('div',[
                createElement('p','純文本組件'),
                createElement('p',this.data.text)
            ]);
        }
    }
    Vue.component('smart-item',{
        // 函數化組件
        functional: true,
        render: function (createElement,context) {
            // 根據傳入的數據桨吊,智能判斷顯示哪種組件
            function getComponent(){
                var data = context.props.data;
                // 判斷prop:data的type字段是屬于哪種類型的組件
                if( data.type === 'img' ) return ImgItem;
                if( data.type === 'video' ) return VideoItem;
                return TextItem;
            }
            return createElement(
                getComponent(),
                {
                    props:{
                        // 把smart-item的prop:data傳給上面智能選擇的組件
                        data: context.props.data
                    }
                },
                // 相當于this.$slots.default
                context.children
            );
        },
        props:{
            data:{
                type: Object,
                required: true
            }
        }
    });

    var app = new Vue({
        el: '#app',
        data: {
            data:{}
        },
        methods:{
            // 切換不同類型組件的數據
            change: function (type) {
                if( type === 'img' ){
                    this.data = {
                        type: 'img',
                        url: 'https://raw.githubusercontent.com/iview/iview/master/assets/logo.png'
                    }
                }else if( type === 'video' ){
                    this.data = {
                        type: 'video',
                        url: 'http://vjs.zencdn.net/v/oceans.mp4'
                    }
                }else if( type === 'text' ){
                    this.data = {
                        type: 'text',
                        content: '這是一段純文本'
                    }
                }
            }
        },
        created: function () {
            // 初始化時,默認設置圖片組件的數據
            this.change('img');
        }
    });
</script>
</body>
</html>

逐步分析一下實現內容凤巨。ImgIten,VideoItem,TextItem這3個對象分別是圖片組件视乐、視頻組件和純文本組件的選項,它們都接收一個prop:data敢茁。在函數化組件smart-item里佑淀,也有props:data,通過getComponent函數來判斷其字段type的值彰檬,選擇這條數據適合渲染的組件伸刃。通過createElement把getComponent()返回的對象設置為第一個參數,然后通過第二個參數把smart-item的data傳遞到選擇的組件里的prop:data逢倍,組件渲染出不同的內容捧颅。
根實例app中的方法change用來生成不同的數據,通過3個button來切換较雕。
該實例難理解的地方在于smart-item和3個功能組件都有prop:data碉哑,它們的傳遞順序和原理看起來比較含糊。
函數化組件在業(yè)務中并不是很常用亮蒋,而且也有其他類似的方法來實現扣典,比如上例也可以用組件的is特性來動態(tài)掛載∩骶粒總結起來贮尖,函數化組件主要適用于以下兩個場景:
1、程序化地在多個組件中選擇一個趁怔。
2湿硝、在將children,props,data 傳遞給子組件之前操作它們薪前。

效果圖:


用組件的is特性實現
<div id="app">
    <component :is="view"></component>
    <button @click="view='component1'">切換為圖片組件</button>
    <button @click="view='component2'">切換為視頻組件</button>
    <button @click="view='component3'">切換為文本組件</button>
</div>
<script>
    Vue.component('component1',{
        template:'<div><p>圖片組件</p><img src="https://raw.githubusercontent.com/iview/iview/master/assets/logo.png"></div>'
    });
    Vue.component('component2',{
        template: '<div><p>視頻組件</p><video src="http://vjs.zencdn.net/v/oceans.mp4" controls="controls" autoplay="autoplay"></video></div>'
    });
    Vue.component('component3',{
        template: '<div><p>純文本組件</p><p>這是一段純文本</p></div>'
    });
    var app = new Vue({
        el: '#app',
        data: {
            view: 'component1'
        }
    });
</script>
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市图柏,隨后出現的幾起案子序六,更是在濱河造成了極大的恐慌,老刑警劉巖蚤吹,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件例诀,死亡現場離奇詭異,居然都是意外死亡裁着,警方通過查閱死者的電腦和手機繁涂,發(fā)現死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來二驰,“玉大人扔罪,你說我怎么就攤上這事⊥叭福” “怎么了矿酵?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長矗积。 經常有香客問我全肮,道長,這世上最難降的妖魔是什么棘捣? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任辜腺,我火速辦了婚禮,結果婚禮上乍恐,老公的妹妹穿的比我還像新娘评疗。我一直安慰自己,他們只是感情好茵烈,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布百匆。 她就那樣靜靜地躺著,像睡著了一般瞧毙。 火紅的嫁衣襯著肌膚如雪胧华。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天宙彪,我揣著相機與錄音矩动,去河邊找鬼。 笑死释漆,一個胖子當著我的面吹牛悲没,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼示姿,長吁一口氣:“原來是場噩夢啊……” “哼甜橱!你這毒婦竟也來了?” 一聲冷哼從身側響起栈戳,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤岂傲,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后子檀,有當地人在樹林里發(fā)現了一具尸體镊掖,經...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年褂痰,在試婚紗的時候發(fā)現自己被綠了亩进。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡缩歪,死狀恐怖归薛,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情匪蝙,我是刑警寧澤主籍,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站逛球,受9級特大地震影響崇猫,放射性物質發(fā)生泄漏。R本人自食惡果不足惜需忿,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜡歹。 院中可真熱鬧屋厘,春花似錦、人聲如沸月而。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽父款。三九已至溢谤,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間憨攒,已是汗流浹背世杀。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留肝集,地道東北人瞻坝。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像杏瞻,于是被迫代替她去往敵國和親所刀。 傳聞我的和親對象是個殘疾皇子衙荐,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內容