使用vue組件需要注意的4個細節


 

 

  細節1:table(表格)直接引用自定義組件出現的bug

    

    如上圖,tr本應在tbody中面,現在卻是同級。造成的原因是h5規定table里必須有tbodytbody中必須有tr

     tbody中引入自定義組件,瀏覽器解析后就出現了上述問題

  

       解決方法:依然在tbody中使用tr,同時使用vueis屬性,

          該屬性可理解為我想使用一個組件,但不能直接使用,雖然我這里寫的是tr,但實際使用的是自定義組件,

          同時建議ul中的li, select里的option都使用is屬性,以防止上述問題的出現

    

   DEMO

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="root">
            <table>
                <tbody>
                    <tr is="row"></tr>
                    <tr is="row"></tr>
                    <tr is="row"></tr>
                </tbody>
            </table>
        </div>

        <script>
            Vue.component("row", {
                template: "<tr><td>this is a row</td></tr>"
            })
            
            var vm = new Vue({
                el: '#root'
            })
        </script>
    </body>

</html>

 

 

  細節2:子組件里面的data必須是一個函數

    下面寫法data是一個對象,而不是函數vue根實例中(也就是父組件中)這種寫法沒有問題

      

       若在子組件中,上述的寫法會報錯,提示data選項應該是一個函數,並且要返回一個對象

       

      

       注:目的是為了讓每個實例可以維護一份被返回對象的獨立的拷貝

      上面子組件data的寫法用es6如下

       

 

 

  細節3:使用vue提供的ref屬性為元素或子組件注冊引用信息,從而操作DOM

      ref為元素注冊引用操作dom

     下面代碼中this指向vue根實例,$refs指根實例下所有引用,hello是設置的元素引用名字,  innerHTML是獲取hello world文字信息

          也可簡單理解為ref屬性幫我們獲取到某個dom節點,ref = 'dom節點的名字,可以自定義'

  DEMO

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="root">
            <div ref="hello" @click="handleClick">hello world</div>
        </div>

        <script>
            var vm = new Vue({
                el: '#root',
                methods: {
                    handleClick: function() {
                        console.log(this.$refs.hello.innerHTML);
                    }
                }
            })
        </script>
    </body>

</html>

 

     ref為子組件注冊引用操作dom(下面示例為點擊后,計數求和)

    

 

  DEMO

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>

    <body>
        <div id="root">
            <counter ref="one" @change="handleChange"></counter>
            <counter ref="two" @change="handleChange"></counter>
            <div>計數:{{total}}</div>
        </div>

        <script>
            Vue.component("counter", {
                template: "<div @click='handleClick'>{{number}}</div>",
                data: function() {
                    return {
                        number: 0
                    }
                },
                methods: {
                    handleClick: function() {
                        this.number++;
                        this.$emit("change");
                    }
                }
            })
            
            var vm = new Vue({
                el: '#root',
                data: {
                    total: 0
                },
                methods: {
                    handleChange: function() {
                        this.total = this.$refs.one.number + this.$refs.two.number; 
                    }
                }
            })
        </script>
    </body>

</html>

 

 

   細節4:子組件不能修改父組件傳遞過來的值

       父組件通過屬性的形勢可以隨意給子組件傳遞值,但子組件不能修改父組件的數據,

       否則會有一個警告,提示不要直接修改父組件傳遞過來的值

       

       注:因為vue有單項數據流機制,這個機制不會讓子組件修改父組件的值

 

       單項數據流是為了避免下面情況:      

         當子組件接收的不是一個基本類型(比如number,string, boolean),而是一個對象(引用類型)時,

        在子組件中改變了父組件傳遞過來的值(比如下面示例代碼中子組件接收的count值)可能這個值還被其它子組件所使用,這樣其它子組件也會受影響

  

  DEMO

<!DOCTYPE html>
<html>
     <head>
           <meta charset="UTF-8">
           <title>父子組件間的數據傳遞-進階</title>
           <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
     </head>
     <body>
           <div id="root">
                <counter :count='1'></counter>
                <counter :count='2'></counter>
           </div>
           
           <script>
                var counterTemplate = {
                     props: ['count'],
                     template: '<div @click="handleClick">{{count}}</div>',
                     methods: {
                           handleClick: function() {
                                this.count++
                           }
                     }
                }
                
                var vm = new Vue({
                     el: '#root',
                     components: {
                           'counter': counterTemplate
                     }
                })
           </script>
     </body>
</html>

 

      但有時需要在子組件中改變父組件傳遞過來的值,該怎么辦呢?
 
     在子組件中定義一個data(子組件的data必須是一個函數),然后返回一個對象,在對象中定義一個number的數據,初始值是this.count
 
       相當於子組件接收了父組件傳遞過來的值(這里指count),接着復制一份,
    然后放到子組件自己的data里面,每次點擊后,被修改的是子組件自己的值(父組件傳遞過來的值的副本),而不是直接修改父組件傳遞過來的原始值
 
  DEMO
<!DOCTYPE html>
<html>
     <head>
           <meta charset="UTF-8">
           <title>父子組件間的數據傳遞-進階</title>
           <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
     </head>
     <body>
           <div id="root">
                <counter :count='1'></counter>
                <counter :count='2'></counter>
           </div>
           
           <script>
                var counterTemplate = {
                     props: ['count'],
                     data: function() {
                           return {
                                number: this.count
                           }
                     },
                     template: '<div @click="handleClick">{{number}}</div>',
                     methods: {
                           handleClick: function() {
                                this.number++
                           }
                     }
                }
                
                var vm = new Vue({
                     el: '#root',
                     components: {
                           'counter': counterTemplate
                     }
                })
           </script>
     </body>
</html>

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM