Vue.js,學習心得(十四)組件四

學習心得,
組件(四),

直接上代碼了

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

<!--編寫可復用組件-->

<!--在編寫組件時,最好考慮好以后是否要進行復用。-->
<!--一次性組件間有緊密的耦合沒關系,但是可復用組件應當定義一個清晰的公開接口,同時也不要對其使用的外層數據作出任何假設。-->
<!--Vue 組件的 API 來自三部分——prop、事件和插槽:-->
<!--Prop 允許外部環境傳遞數據給組件;-->
<!--事件允許從組件內觸發外部環境的副作用;-->
<!--插槽允許外部環境將額外的內容組合在組件中。-->
<!--使用 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
    //當 ref 和 v-for 一起使用時,獲取到的引用會是一個數組,包含和循環數據源對應的子組件。
    //$refs 只在組件渲染完成后才填充,并且它是非響應式的。
    // 它僅僅是一個直接操作子組件的應急方案——應當避免在模板或計算屬性中使用 $refs。
</script>

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

    </async-example>
</div>
<hr>
<script>
//    異步組件
//
//    在大型應用中,我們可能需要將應用拆分為多個小模塊,按需從服務器下載。
//為了進一步簡化,Vue.js 允許將組件定義為一個工廠函數,異步地解析組件的定義。
//Vue.js 只在組件需要渲染時觸發工廠函數,并且把結果緩存起來,用于后面的再次渲染。
//例如:
    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>
    //工廠函數接收一個 resolve 回調,在收到從服務器下載的組件定義時調用。
    //也可以調用 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'
//    });


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


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

//    如果你是 Browserify 用戶,可能就無法使用異步組件了,
//    它的作者已經表明 Browserify 將“永遠不會支持異步加載”。
//    Browserify 社區發現了一些解決方法,可能會有助于已存在的復雜應用。
//    對于其他場景,我們推薦使用 webpack,因為它對異步加載進行了內置、全面的支持。
</script>


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

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

//    注意,當一個異步組件被作為 vue-router 的路由組件使用時,
//這些高級選項都是無效的,因為在路由切換前就會提前加載所需要的異步組件。
//另外,如果你要在路由組件中使用上述寫法,需要使用 vue-router 2.4.0 以上的版本。
</script>
<script>
//    組件命名約定
//
//    當注冊組件 (或者 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>
//    當使用字符串模式時,可以不受 HTML 大小寫不敏感的限制。
// 這意味實際上在模板中,你可以使用下面的方式來引用你的組件:
//kebab-case
//    camelCase 或 kebab-case (如果組件已經被定義為 camelCase)
//    kebab-case、camelCase 或 PascalCase (如果組件已經被定義為 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 是最通用的使用約定。
//如果組件未經 slot 元素傳入內容,你甚至可以在組件名后使用 / 使其自閉合:
//    <my-component/>
//    當然,這只在字符串模板中有效。因為自閉的自定義元素是無效的 HTML,瀏覽器原生的解析器也無法識別它。
</script>
<script>
//    遞歸組件
//
//    組件在它的模板內可以遞歸地調用自己。不過,只有當它有 name 選項時才可以這么做:
//name: 'unique-name-of-my-component'
//    當你利用 Vue.component 全局注冊了一個組件,全局的 ID 會被自動設置為組件的 name。
//Vue.component('unique-name-of-my-component', {
//    // ...
//})
//    如果稍有不慎,遞歸組件可能導致死循環:
//name: 'stack-overflow',
//    template: '<div><stack-overflow></stack-overflow></div>'
//    上面組件會導致一個“max stack size exceeded”錯誤,所以要確保遞歸調用有終止條件 (比如遞歸調用時使用 v-if 并最終解析為 false)。
</script>
<script>
//    組件間的循環引用
//
//    假設你正在構建一個文件目錄樹,像在 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>
//    當你仔細看時,會發現在渲染樹上這兩個組件同時為對方的父節點和子節點——這是矛盾的!
// 當使用 Vue.component 將這兩個組件注冊為全局組件的時候,框架會自動為你解決這個矛盾。如果你已經是這樣做的,就跳過下面這段吧。
//然而,如果你使用諸如 webpack 或者 Browserify 之類的模塊化管理工具來 require/import 組件的話,就會報錯了:
//Failed to mount component: template or render function not defined.
//        為了解釋為什么會報錯,簡單的將上面兩個組件稱為 A 和 B。模塊系統看到它需要 A,但是首先 A 需要 B,但是 B 需要 A,而 A 需要 B,循環往復。
// 因為不知道到底應該先解析哪個,所以將會陷入無限循環。要解決這個問題,我們需要在其中一個組件中告訴模塊化管理系統:“A 雖然最后會用到 B,但是不需要優先導入 B”。
//在我們的例子中,可以選擇讓 tree-folder 組件中來做這件事。
// 我們知道引起矛盾的子組件是 tree-folder-contents,所以我們要等到 beforeCreate 生命周期鉤子中才去注冊它:
//beforeCreate: function () {
//    this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue')
//}
//    問題解決了!
</script>

<script>
//    內聯模板
//
//    如果子組件有 inline-template 特性,組件將把它的內容當作它的模板,而不是把它當作分發內容。這讓模板編寫起來更靈活。
//    <my-component inline-template>
//    <div>
//    <p>這些將作為組件自身的模板。</p>
//    <p>而非父組件透傳進來的內容。</p>
//    </div>
//    </my-component>
//    但是 inline-template 讓模板的作用域難以理解。使用 template 選項在組件內定義模板或者在 .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'
    })
//    這在有很多大模板的演示應用或者特別小的應用中可能有用,其它場合應該避免使用,因為這將模板和組件的其它定義分離了。
</script>

<script>
//    對低開銷的靜態組件使用 v-once
//
//    盡管在 Vue 中渲染 HTML 很快,不過當組件中包含大量靜態內容時,可以考慮使用 v-once 將渲染結果緩存起來,就像這樣:
//Vue.component('terms-of-service', {
//    template: '\
//    <div v-once>\
//      <h1>Terms of Service</h1>\
//      ...很多靜態內容...\
//    </div>\
//  '
//})
</script>
</body>
</html>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內容