vue、react隱式實例化

這是一篇幾個月前寫的文章,那時候理解也不是特別透徹,但仍是搬運到掘金髮一遍。html

寫這篇的原因是由於上一篇vue與react組件對比學習寫的有點囉嗦也沒有寫的很明白同時也存在一點錯誤,因此從新寫一篇簡介概要點的。vue

隱式實例化

隱式實例化,不但願寫在reactjsx裏或是vuetemplate,而是但願經過手動去實例化一個react或是vue組件。node

說的有點繞,這種隱式實例化的應用場景在提示信息(message)、模態框(modal)、加載條(loadingbar),例如一個ajax請求,在成功或失敗的時候須要給一個提示:react

// 下面是僞代碼...

import message from 'message'

fetch('/api/xxx')
    .then(resp => {
        if(resp.success === true){
            message({
                type:"success",
                text:"請求成功"
            })
        } else {
            message({
                type:"error",
                text:"請求出錯"
            })
        }
    })

複製代碼

能夠看的出來,咱們的需求是想有一個組件能像html原生的alert同樣,在須要的地方可以直接去調用,而不是須要把message組件寫進節點中。git

難點

咱們都知道不管是react、仍是vue也好,寫的都是一個類或者叫構造器:github

// react 引用代碼省略

export default class Message extends React.Component{}

// vue
// export default {
    data(){},
    props:{},
    methods:{},
    render:function(){}
}


複製代碼

react至關明顯地建立了一個classvue表面上好像只是暴露一個對象,實際上vue的組件被使用時,你須要把子組件傳入父組件的component的對象中,因此Vue會調用Vue.extend({...自組建的選項對象}),這個方法就返回了一個構造器。ajax

既然知道了子組件是一個構造器,那我能不能直接去手動new一個子組件呢?在我測試下來,好像是不行。api

vue實例化

那麼如何實例化呢?分紅兩部分,先是實例化一個組件,而後再把實例化後的組件掛載到html中去。先拿vue說:app

拿到構造器

import Vue from 'vue'
import message from './message.vue'

// 注意: 這裏的message僅僅就是一個對象,須要轉成構造器

const messageConstructor = Vue.extend(message)


複製代碼

實例化

const customProps = {
    // 傳給組件的一些props
}


// 這樣就能拿到了一個vue組件的實例,就能作不少事情了,好比調用實例中寫好的methods中的方法,固然這還沒完,咱們還得把實例掛載到Html中
const messageInstance = new messageConstuctor({propsData:customProps})
複製代碼

掛載

vue的實例有一個很重要的方法:$mount,在選項對象中咱們沒有傳入el屬性,因此你在這裏手動實例化的vue實例是沒有掛載出來的,須要手動調用一遍$mount,能夠傳入一個DOM節點作爲掛載節點,固然也能夠不傳入參數,後面手動用dom方法把節點插入。iview

// 這裏返回的messageWithDom依然仍是vue實例而不是dom節點,可是這個實例多了一個$el屬性,這個屬性裏面就藏着咱們須要掛載的dom節點
const messageWithDom = messageInstance.$mount()

const dom = messageWithDom.$el

document.body.appendChild(dom)

複製代碼

野路子

vue隱式化實例,基本是這個套路,固然我在看iview組件庫中用了一些其餘的野路子,這裏也貼一下:

import Notification from './notification.vue';
import Vue from 'vue';

const _props = properties || {};

const Instance = new Vue({
    render (h) {
        return h(Notification, {
            props: _props
        });
    }
});

複製代碼

道理基本上和我說的差很少,不過調用Vue.extend更加容易理解。

後續控制

拿到組件的實例後,基本上想怎麼玩就能怎麼玩了,好比說控制隱藏或顯示,能夠在組件內部定義一個isShowdata屬性,在實例上能夠這樣用:

if( xxxx ) {
    messageWithDom.isShow = true
} else {
    messageWithDom.isShow = false
}

複製代碼

react實例化

react的實例化和vue稍稍不一樣,首先引進來的直接就是一個類因此不須要像Vue同樣多作一步轉換成構造器,其次react是沒有相似vue$mount方法,這也是我一開始很疑惑的地方,後來忽然想起來react把組件的掛載方法放到了reactDom這個包裏面了。

建立一個虛擬dom

這裏須要調用React.createElement去建立一個虛擬dom,其實vue也能建立一個虛擬dom,參考上面iview的野路子。

import React from 'react'
import Message from './message.jsx'

const customProps = {
    // 傳給自組件的一些props
}

const Vnode = React.createElment(Message,{props:customProps})

複製代碼

掛載而且拿到實例

react沒有$mount方法,而是直接調用reactDomrender方法,至關於vue的兩步直接一步完成:

import React from 'react'
import ReactDom from 'react-dom'

const containner = document.createElement('div')
document.body.appendChild(containner)

// 把虛擬dom傳入reactDom.render方法中,第二個參數是掛載的節點,並返回這個組件的實例
const messageInstance = ReactDom.render(Vnode,containner)
複製代碼

後續的控制

拿到組件的實例後,基本想怎麼玩就能怎麼玩了,可是別忘記了!!!react修改state是調用setState,而不像vue直接修改。

總結

學會隱式化建立實例可以很好的看清楚vuereact內部的細節,對提升vuereact大有好處。個人一個項目有個加載條的組件,同時用reactvue都實現了一遍,能夠對比學習發現二者的差別,喜歡的能夠點個贊~~。

相關文章
相關標籤/搜索