Vue組件基礎

一、Vue組件概念

組件是可復用的 Vue 實例,且帶有一個名字,例如:

  Vue.component("input-content", {
            data: function () {
                return {
                    message: ""
                }
            },
            template: `<div>
                    <input type="text" v-model="message">
                    <p>輸入的值為{{message}}</p>
                  </div>`
        });

在這個例子中,組件的名字是:input-content, 可以通過new Vue 創建的 Vue 根實例中,把這個組件作為自定義元素來使用

<div id="app">
        <input-content></input-content>
    </div>

因為組件是可復用的 Vue 實例,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命周期鉤子等。僅有的例外是像 el 這樣根實例特有的選項。

二、Vue組件組織

為了能在模板中使用,這些組件必須先注冊以便 Vue 能夠識別。這里有兩種組件的注冊類型:全局注冊和局部注冊。全局注冊的組件可以用在其被注冊之后的任何 (通過 new Vue) 新創建的 Vue 根實例,也包括其組件樹中的所有子組件的模板中。

三、組件傳值

組件傳值主要有父組件向子組件傳值子組件向父組件傳值

  • 父組件向子組件傳值:通過prop向子組件傳遞數據

舉例說明:

<body>
    <div id="app">
        <input-content :content="message"></input-content>

    </div>
    <script src="js/vue.js"></script>
    <script>
        Vue.component("input-content", {
            props: ["content"],
            data: function () {
                return {
                    content: ""
                }
            },
            template: `<div>
                    <p>父組件傳過來的值為:{{content}}</p>
                  </div>`
        });
        const vm = new Vue({
            el: '#app',
            data: {
                message: 56
            }
        });
    </script>
</body>F

上面這段代碼定義了父組件中的message的值通過props向子組件<input-content></input-content>傳入,具體步驟如下。

  • 第一步 :子組件首先定義一個props選項,表示已經準備好接收來自父組件中message數據。
  • 第二步:子組件準備接受數據的時候就在標簽里說明一下我要接收的是父組件的message數據,也就是上面代碼中的<input-content :content="message"></input-content>,這樣父組件中的message數據就傳給子組件了。這里傳值的時候注意了,如果傳的是對象或者數組就必須綁定才能接收到,如果是靜態數值就不需要綁定。

  • 子組件向父組件傳值,用一個書籍管理來舉例
書籍

上面是效果圖,思路是這樣的,輸入書籍的信息后,在表格里顯示出來,這里運用Vue組件傳值的思路,將書籍信息的輸入框作為子組件,顯示的表格作為父組件,也可以反著來,輸入框作為父組件。表格作為子組件,這里主要為練習子組件向父組件傳值。

  • 首先布局用bootstrap,就不做過多介紹
  • 接下來是綁定數據,就是將輸入的書籍信息作為一個數組傳給父組件顯示出來
    1.首先定義子組件,將表單作為template模版寫入子組件中
Vue.component("book-list", {
        data: function () {
            return {
            }
        },
        template: `
             <form action=""> 
                    <div class="form-group">
                        <label for="exampleInputEmail1">書名</label>
                        <input type="text" class="form-control" id="exampleInputEmail1">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">作者</label>
                        <input type="text" class="form-control" id="exampleInputPassword1">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">價格</label>
                        <input type="text" class="form-control" id="exampleInputPassword1">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">數量</label>
                        <input type="text" class="form-control" id="exampleInputPassword1">
                    </div>
                    <button type="button" class="btn btn-default" @click="addbook">添加書籍</button>
                </form>
                `,
    });

2.在data里定義四個對象,分別與書籍信息的四個屬性綁定

 Vue.component("book-list", {
        props: ["books"],
        data: function () {
            return {
                name: "",            //與書名綁定
                author: "",            //與作者綁定
                price: "",            //與價格綁定
                number: "",            //與數量綁定
            }
        },
        template: `
             <form action=""> 
                    <div class="form-group">
                        <label for="exampleInputEmail1">書名</label>
                        <input type="text" class="form-control" id="exampleInputEmail1" v-model.lazy="name">`
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">作者</label>
                        <input type="text" class="form-control" id="exampleInputPassword1" v-model.lazy="author">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">價格</label>
                        <input type="text" class="form-control" id="exampleInputPassword1" v-model.lazy.number="price">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">數量</label>
                        <input type="text" class="form-control" id="exampleInputPassword1" v-model.lazy.number="number">
                    </div>
                    <button type="button" class="btn btn-default" @click="addbook">添加書籍</button>
                </form>
                    `,
    });
  • 將書籍信息添加到定義的一個books數組中去
    1 .由于books數組在父組件中,這里就步入正題了,子組件向父組件傳值。先定義一個book對象,來裝綁定的書籍信息
    methods: {
            addbook: function () {
                const book = {
                    name: this.name,
                    author: this.author,
                    price: this.price,
                    number: this.number
                };
            },
        },

2.那么這個book對象要如何傳到父組件中去呢,這里用到監聽子組件事件$emit方法,就好比是一個人給另一個人寄東西,寄東西需要啥?有要寄去的東西,有寄東西的方式,還要有對方的地址。這里就當是把書籍信息book寄到books數組中去,寄的東西有了,那么我怎么寄?選什么快遞?$emit方法就好比是快遞。這個快遞有啥?是不是有寄的東西,有地址。this.$emit("book", book);第一個book就相當于是地址,第二個book相當于是要寄的東西。快遞送到了我要怎么去通知父組件?這個時候就用到了<book-list @book="addbook"></book-list>。就說在某某快遞來取東西,這個時候父組件就知道了東西寄到了。那么book對象傳到了,就到了下一步。
3.將book添加到books數組中

 data: {
            books: [],
        },
 methods: {
            addbook: function (book) {
                this.books.push(book);
            }
        }

4.在父組件中用v-for方法遍歷books數組

           <tr v-for="(content,index) in books">
                    <td>{{index+1}}</td>
                    <td>{{content.name}}</td>
                    <td>{{content.author}}</td>
                    <td><input type="number" name="" id="" v-model.number="content.price"></td>
                    <td><input type="number" name="" id="" v-model.number="content.number"></td>
                    <td><button @click="delebook">刪除</button></td>
                </tr>

這個時候就實現了添加書籍信息顯示在列表中這一基本功能。但是會發現這本書沒有編號,一開始的想法是用數組下標來作為編號,這時就出現了一個問題,當刪除一本書的時候,就會把后面的編號打亂,就沒有達到給一本書編號的的基本功能,解決方法是用獲取當前數組的長度作為書的編號,添加一本書數組的長度就加1,再把當前數組長度作為當前書籍的編號,所以再刪除一本書的時候就不會對書的編號產生影響
5.獲取數組長度作為書籍編號,但是數組定義在了父元素上,所以就用props屬性來給子元素傳值,然后再回傳給父元素作為書籍的編號。這里props屬性的運用就不做過多介紹了。
6.源碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>書籍管理</title>
    <link rel="stylesheet" href="css/bootstrap.css">
    <style>
        input {
            width: 55px;
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="container">
            <h3>書籍管理系統</h3>
            <table class="table table-striped table-bordered">
                <tr>
                    <th>序號</th>
                    <th>編號</th>
                    <th>名稱</th>
                    <th>作者</th>
                    <th>價格</th>
                    <th>數量</th>
                    <th>操作</th>
                </tr>
                <tr v-for="(content,index) in books">
                    <td>{{index+1}}</td>
                    <td>{{content.id}}</td>
                    <td>{{content.name}}</td>
                    <td>{{content.author}}</td>
                    <td><input type="number" name="" id="" v-model.number="content.price"></td>
                    <td><input type="number" name="" id="" v-model.number="content.number"></td>
                    <td><button @click="delebook">刪除</button></td>
                </tr>
                <tr>
                    <td>總價格:{{allprice}}</td>
                </tr>
            </table>
            <div>
                <h4>添加書籍</h4>
                <book-list @book="addbook" :books="books"></book-list>
            </div>
        </div>
    </div>
</body>
<script src="js/jquery-3.4.1.js"></script>
<script src="js/bootstrap.js"></script>
<script src="js/vue.js"></script>
<script>

    Vue.component("book-list", {
        props: ["books"],
        data: function () {
            return {
                name: "",
                author: "",
                price: "",
                number: "",
            }
        },
        template: `
             <form action=""> 
                    <div class="form-group">
                        <label for="exampleInputEmail1">書名</label>
                        <input type="text" class="form-control" id="exampleInputEmail1" v-model.lazy="name">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">作者</label>
                        <input type="text" class="form-control" id="exampleInputPassword1" v-model.lazy="author">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">價格</label>
                        <input type="text" class="form-control" id="exampleInputPassword1" v-model.lazy.number="price">
                    </div>
                    <div class="form-group">
                        <label for="exampleInputPassword1">數量</label>
                        <input type="text" class="form-control" id="exampleInputPassword1" v-model.lazy.number="number">
                    </div>
                    <button type="button" class="btn btn-default" @click="addbook">添加書籍</button>
                </form>
                `,
        methods: {
            addbook: function () {
                const book = {
                    id: this.books.length + 1,
                    name: this.name,
                    author: this.author,
                    price: this.price,
                    number: this.number
                };
                this.$emit("book", book);
            },
        },
    });
    // --------------------------------------------------------------------------------------
    const vm = new Vue({
        el: "#app",
        data: {
            books: [],
        },
        methods: {
            addbook: function (book) {
                this.books.push(book);
            },
            //刪除書籍功能
            delebook: function (index) {
                this.books.splice(index, 1);
            }
        },
        computed: {
            //計算當前書籍的總價
            allprice: function () {
                let totalprice = 0;
                let books = this.books;
                books.forEach(function (book) {
                    totalprice = totalprice + book.price * book.number;
                });
                return totalprice;
            }
        },
    });
</script>

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

推薦閱讀更多精彩內容

  • 組件是可復用的Vue實例,且帶有一個名字。我們可以在一個通過new Vue創建的Vue根實例中,把這個組件作為自定...
    oWSQo閱讀 328評論 0 0
  • 祭出demo 基礎示例 組件是可復用的 Vue 實例,所以它們與 new Vue 接收相同的選項,例如 data、...
    rainbowboy閱讀 861評論 0 50
  • 組件是可復用的 Vue 實例,且帶有一個名字:在這個例子中是 。我們可以在一個通過 new Vue 創建的 Vu...
    波克比閱讀 176評論 0 0
  • 定義組件 Vue.component props 接受父組件的傳值 props也可以接受一個對象 在組件上用v-f...
    豆漿的鏟屎官閱讀 253評論 0 0
  • 作為中國最火的兩位脫口秀演員,李誕和池子都說自己想當作家,李誕至今都不愿意承認自己是個脫口秀演員。 作為《脫口秀大...
    網易王三三閱讀 2,247評論 5 25