Vue.js,學(xué)習(xí)心得(十四)組件四

學(xué)習(xí)心得,
組件(四),

直接上代碼了

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>組件四雜項</title>
    <script src="../js/vue.js"></script>
</head>
<body>
<!--雜項-->

<!--編寫可復(fù)用組件-->

<!--在編寫組件時,最好考慮好以后是否要進行復(fù)用。-->
<!--一次性組件間有緊密的耦合沒關(guān)系吁峻,但是可復(fù)用組件應(yīng)當(dāng)定義一個清晰的公開接口,同時也不要對其使用的外層數(shù)據(jù)作出任何假設(shè)费尽。-->
<!--Vue 組件的 API 來自三部分——prop、事件和插槽:-->
<!--Prop 允許外部環(huán)境傳遞數(shù)據(jù)給組件羊始;-->
<!--事件允許從組件內(nèi)觸發(fā)外部環(huán)境的副作用旱幼;-->
<!--插槽允許外部環(huán)境將額外的內(nèi)容組合在組件中。-->
<!--使用 v-bind 和 v-on 的簡寫語法突委,模板的意圖會更清楚且簡潔:-->
    <my-component
        v-bind:foo = "baz"
        v-bind:bar = "qux"
        v-on:event-a = "doThis"
        v-on:event-b = "doThat"
    >
        <img slot="icon" src="#" >
        <p slot="main-text">Hello!</p>
    </my-component>
<!--子組件引用-->

<!--盡管有 prop 和事件柏卤,但是有時仍然需要在 JavaScript 中直接訪問子組件。-->
<!--為此可以使用 ref 為子組件指定一個引用 ID匀油。例如:-->
<div id="parent">
    <user-profile ref="profile"></user-profile>
</div>
<hr>
<script>
    Vue.component('my-component',{
        template:''
    });
    Vue.component('user-profile',{
        template:'<p></p>'
    });
    var parent = new Vue({ el: '#parent'})
    // 訪問子組件實例
    var child = parent.$refs.profile
    //當(dāng) ref 和 v-for 一起使用時闷旧,獲取到的引用會是一個數(shù)組,包含和循環(huán)數(shù)據(jù)源對應(yīng)的子組件钧唐。
    //$refs 只在組件渲染完成后才填充,并且它是非響應(yīng)式的匠襟。
    // 它僅僅是一個直接操作子組件的應(yīng)急方案——應(yīng)當(dāng)避免在模板或計算屬性中使用 $refs钝侠。
</script>

<div id="app-1">
    <async-example>

    </async-example>
</div>
<hr>
<script>
//    異步組件
//
//    在大型應(yīng)用中,我們可能需要將應(yīng)用拆分為多個小模塊酸舍,按需從服務(wù)器下載帅韧。
//為了進一步簡化,Vue.js 允許將組件定義為一個工廠函數(shù)啃勉,異步地解析組件的定義忽舟。
//Vue.js 只在組件需要渲染時觸發(fā)工廠函數(shù),并且把結(jié)果緩存起來,用于后面的再次渲染叮阅。
//例如:
    Vue.component('async-example',function(resolve,reject){
        setTimeout(function(){
            //將組建定義傳入resolve
            resolve({
                template:'<div>I am async!</div>'
            })
        },1000)
    });
    var app1 = new Vue({
        el:'#app-1'
    });

</script>
<div id="app-2">
    <async-webpack-example>

    </async-webpack-example>
</div>
<hr>
<script>
    //工廠函數(shù)接收一個 resolve 回調(diào)刁品,在收到從服務(wù)器下載的組件定義時調(diào)用。
    //也可以調(diào)用 reject(reason) 指示加載失敗浩姥。
    //這里使用 setTimeout 只是為了演示挑随,實際上如何獲取組件完全由你決定。
    //推薦配合 webpack 的代碼分割功能 來使用:

//    Vue.component(
//        'async-webpack-example',function(resolve){
//            // 這個特殊的 require 語法告訴 webpack
//            // 自動將編譯后的代碼分割成不同的塊勒叠,
//            // 這些塊將通過 Ajax 請求自動下載兜挨。
//            require(['./my-async-component'],resolve)
//        });
//    var app2 = new Vue({
//        el:'#app-2'
//    });


//    你可以在工廠函數(shù)中返回一個 Promise,所以當(dāng)使用 webpack 2 + ES2015 的語法時可以這樣:
//Vue.component(
//    'async-webpack-example',
//    // 該 `import` 函數(shù)返回一個 `Promise` 對象眯分。
//    () => import('./my-async-component')
//    )


//    當(dāng)使用局部注冊時拌汇,也可以直接提供一個返回 Promise 的函數(shù):
//new Vue({
//    // ...
//    components: {
//        'my-component': () => import('./my-async-component')
//}
//    })

//    如果你是 Browserify 用戶,可能就無法使用異步組件了弊决,
//    它的作者已經(jīng)表明 Browserify 將“永遠不會支持異步加載”噪舀。
//    Browserify 社區(qū)發(fā)現(xiàn)了一些解決方法,可能會有助于已存在的復(fù)雜應(yīng)用丢氢。
//    對于其他場景傅联,我們推薦使用 webpack,因為它對異步加載進行了內(nèi)置疚察、全面的支持蒸走。
</script>


<script>
//    高級異步組件
//
//    2.3.0 新增
//    自 2.3.0 起,異步組件的工廠函數(shù)也可以返回一個如下的對象:

//const AsyncComp = () => ({
//// 需要加載的組件貌嫡。應(yīng)當(dāng)是一個 Promise
//        component: import('./MyComp.vue'),
//// 加載中應(yīng)當(dāng)渲染的組件
//        loading: LoadingComp,
//// 出錯時渲染的組件
//        error: ErrorComp,
//// 渲染加載中組件前的等待時間比驻。默認:200ms。
//        delay: 200,
//// 最長等待時間岛抄。超出此時間則渲染錯誤組件别惦。默認:Infinity
//        timeout: 3000
//    })

//    注意,當(dāng)一個異步組件被作為 vue-router 的路由組件使用時夫椭,
//這些高級選項都是無效的掸掸,因為在路由切換前就會提前加載所需要的異步組件。
//另外蹭秋,如果你要在路由組件中使用上述寫法扰付,需要使用 vue-router 2.4.0 以上的版本。
</script>
<script>
//    組件命名約定
//
//    當(dāng)注冊組件 (或者 prop) 時仁讨,可以使用 kebab-case (短橫線分隔命名)羽莺、camelCase (駝峰式命名) 或 PascalCase (單詞首字母大寫命名)。
//    // 在組件定義中
//    components: {
//        // 使用 kebab-case 注冊
//        'kebab-cased-component': { /* ... */ },
//        // 使用 camelCase 注冊
//        'camelCasedComponent': { /* ... */ },
//        // 使用 PascalCase 注冊
//        'PascalCasedComponent': { /* ... */ }
//    }
//    在 HTML 模板中洞豁,請使用 kebab-case:
//    <!-- 在 HTML 模板中始終使用 kebab-case -->
//    <kebab-cased-component></kebab-cased-component>
//    <camel-cased-component></camel-cased-component>
//    <pascal-cased-component></pascal-cased-component>
//    當(dāng)使用字符串模式時盐固,可以不受 HTML 大小寫不敏感的限制荒给。
// 這意味實際上在模板中,你可以使用下面的方式來引用你的組件:
//kebab-case
//    camelCase 或 kebab-case (如果組件已經(jīng)被定義為 camelCase)
//    kebab-case刁卜、camelCase 或 PascalCase (如果組件已經(jīng)被定義為 PascalCase)
//    components: {
//        'kebab-cased-component': { /* ... */ },
//        camelCasedComponent: { /* ... */ },
//        PascalCasedComponent: { /* ... */ }
//    }
//    <kebab-cased-component></kebab-cased-component>
//    <camel-cased-component></camel-cased-component>
//    <camelCasedComponent></camelCasedComponent>
//    <pascal-cased-component></pascal-cased-component>
//    <pascalCasedComponent></pascalCasedComponent>
//    <PascalCasedComponent></PascalCasedComponent>
//    這意味著 PascalCase 是最通用的聲明約定而 kebab-case 是最通用的使用約定志电。
//如果組件未經(jīng) slot 元素傳入內(nèi)容,你甚至可以在組件名后使用 / 使其自閉合:
//    <my-component/>
//    當(dāng)然长酗,這只在字符串模板中有效溪北。因為自閉的自定義元素是無效的 HTML,瀏覽器原生的解析器也無法識別它夺脾。
</script>
<script>
//    遞歸組件
//
//    組件在它的模板內(nèi)可以遞歸地調(diào)用自己之拨。不過,只有當(dāng)它有 name 選項時才可以這么做:
//name: 'unique-name-of-my-component'
//    當(dāng)你利用 Vue.component 全局注冊了一個組件咧叭,全局的 ID 會被自動設(shè)置為組件的 name蚀乔。
//Vue.component('unique-name-of-my-component', {
//    // ...
//})
//    如果稍有不慎,遞歸組件可能導(dǎo)致死循環(huán):
//name: 'stack-overflow',
//    template: '<div><stack-overflow></stack-overflow></div>'
//    上面組件會導(dǎo)致一個“max stack size exceeded”錯誤菲茬,所以要確保遞歸調(diào)用有終止條件 (比如遞歸調(diào)用時使用 v-if 并最終解析為 false)吉挣。
</script>
<script>
//    組件間的循環(huán)引用
//
//    假設(shè)你正在構(gòu)建一個文件目錄樹,像在 Finder 或資源管理器中婉弹。你可能有一個 tree-folder 組件:
//    <p>
//    <span>{{ folder.name }}</span>
//    <tree-folder-contents :children="folder.children"/>
//        </p>
//    以及一個 tree-folder-contents 組件:
//    <ul>
//    <li v-for="child in children">
//        <tree-folder v-if="child.children" :folder="child"/>
//        <span v-else>{{ child.name }}</span>
//    </li>
//    </ul>
//    當(dāng)你仔細看時睬魂,會發(fā)現(xiàn)在渲染樹上這兩個組件同時為對方的父節(jié)點和子節(jié)點——這是矛盾的!
// 當(dāng)使用 Vue.component 將這兩個組件注冊為全局組件的時候镀赌,框架會自動為你解決這個矛盾氯哮。如果你已經(jīng)是這樣做的焰雕,就跳過下面這段吧拜轨。
//然而膝宁,如果你使用諸如 webpack 或者 Browserify 之類的模塊化管理工具來 require/import 組件的話涤久,就會報錯了:
//Failed to mount component: template or render function not defined.
//        為了解釋為什么會報錯,簡單的將上面兩個組件稱為 A 和 B鹅很。模塊系統(tǒng)看到它需要 A醉者,但是首先 A 需要 B啼器,但是 B 需要 A玛追,而 A 需要 B税课,循環(huán)往復(fù)。
// 因為不知道到底應(yīng)該先解析哪個痊剖,所以將會陷入無限循環(huán)伯复。要解決這個問題,我們需要在其中一個組件中告訴模塊化管理系統(tǒng):“A 雖然最后會用到 B邢笙,但是不需要優(yōu)先導(dǎo)入 B”。
//在我們的例子中侍匙,可以選擇讓 tree-folder 組件中來做這件事氮惯。
// 我們知道引起矛盾的子組件是 tree-folder-contents叮雳,所以我們要等到 beforeCreate 生命周期鉤子中才去注冊它:
//beforeCreate: function () {
//    this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue')
//}
//    問題解決了!
</script>

<script>
//    內(nèi)聯(lián)模板
//
//    如果子組件有 inline-template 特性妇汗,組件將把它的內(nèi)容當(dāng)作它的模板帘不,而不是把它當(dāng)作分發(fā)內(nèi)容。這讓模板編寫起來更靈活杨箭。
//    <my-component inline-template>
//    <div>
//    <p>這些將作為組件自身的模板寞焙。</p>
//    <p>而非父組件透傳進來的內(nèi)容。</p>
//    </div>
//    </my-component>
//    但是 inline-template 讓模板的作用域難以理解互婿。使用 template 選項在組件內(nèi)定義模板或者在 .vue 文件中使用 template 元素才是最佳實踐捣郊。
</script>

<!--X-Template-->

<!--另一種定義模板的方式是在 JavaScript 標簽里使用 text/x-template 類型,并且指定一個 id慈参。例如:-->
<script type="text/x-template" id="hello-world-template">
    <p>Hello hello hello</p>
</script>
<script>
    Vue.component('hello-world', {
        template: '#hello-world-template'
    })
//    這在有很多大模板的演示應(yīng)用或者特別小的應(yīng)用中可能有用呛牲,其它場合應(yīng)該避免使用,因為這將模板和組件的其它定義分離了驮配。
</script>

<script>
//    對低開銷的靜態(tài)組件使用 v-once
//
//    盡管在 Vue 中渲染 HTML 很快娘扩,不過當(dāng)組件中包含大量靜態(tài)內(nèi)容時,可以考慮使用 v-once 將渲染結(jié)果緩存起來壮锻,就像這樣:
//Vue.component('terms-of-service', {
//    template: '\
//    <div v-once>\
//      <h1>Terms of Service</h1>\
//      ...很多靜態(tài)內(nèi)容...\
//    </div>\
//  '
//})
</script>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末琐旁,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子猜绣,更是在濱河造成了極大的恐慌灰殴,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件途事,死亡現(xiàn)場離奇詭異验懊,居然都是意外死亡,警方通過查閱死者的電腦和手機尸变,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進店門义图,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人召烂,你說我怎么就攤上這事碱工。” “怎么了奏夫?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵怕篷,是天一觀的道長。 經(jīng)常有香客問我酗昼,道長廊谓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任麻削,我火速辦了婚禮蒸痹,結(jié)果婚禮上春弥,老公的妹妹穿的比我還像新娘。我一直安慰自己叠荠,他們只是感情好匿沛,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著榛鼎,像睡著了一般逃呼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上者娱,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天抡笼,我揣著相機與錄音,去河邊找鬼肺然。 笑死蔫缸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的际起。 我是一名探鬼主播拾碌,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼街望!你這毒婦竟也來了校翔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤灾前,失蹤者是張志新(化名)和其女友劉穎防症,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哎甲,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡蔫敲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了炭玫。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奈嘿。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖吞加,靈堂內(nèi)的尸體忽然破棺而出裙犹,到底是詐尸還是另有隱情,我是刑警寧澤衔憨,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布叶圃,位于F島的核電站,受9級特大地震影響践图,放射性物質(zhì)發(fā)生泄漏掺冠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一码党、第九天 我趴在偏房一處隱蔽的房頂上張望赫舒。 院中可真熱鬧悍及,春花似錦、人聲如沸接癌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缺猛。三九已至,卻和暖如春椭符,著一層夾襖步出監(jiān)牢的瞬間荔燎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工销钝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留有咨,地道東北人。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓蒸健,卻偏偏與公主長得像座享,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子似忧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容