使用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>
原文地址:https://www.cnblogs.com/tu-0718/p/11177511.html