关于vue中组件的问题

我们今天来聊一下关于vue组件的问题。

1.is的使用
假设有个这样的场景.我希望写一个table表格

常规的HTML结构
<div id="root">
            <table>
                <tbody>
                    <tr>
                        <td>1</td>
                    </tr>
                    <tr>
                        <td>2</td>
                    </tr>
                    <tr>
                        <td>3</td>
                    </tr>
                </tbody>
            </table>
        </div>

那么现在我们希望能通过,vue组件的方式,那么我们看下以下的代码

<div id="root">
            <table>
                <tbody>
                    <row></row>
                    <row></row>
                    <row></row>
                </tbody>
            </table>
        </div>

Vue.component("row",{
                template:"<tr><td>1</td></tr>"
            })

            new Vue({
                el:"#root"
            })

打开浏览器你会发现好像和原来的表格没有多大的区别,但是我们打开控制台查看DOM元素就会发现,我们的tr在在table的外面,这是不符合我们W3C编码的标准的。那么怎么解决这个问题呢?

在vue中,它为这种情况提供了一个解决方法,我们来看下怎么解决这个问题。

<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>1</td></tr>"
            })

            new Vue({
                el:"#root"
            })

        </script>

这个时候我们打开控制台,就会发现它的结构就已经符合我们W3C的编码标准了。其实呢,像这种符合标签还有很多例如,,这个标签下面是要添加option的,那么我们来看下以下代码,

<div id="root">
            <select>
                <row></row>
                <row></row>
                <row></row>
                <row></row>
            </select>
        </div>

        <script>
            Vue.component("row",{
                template:"<option>1</option>"
            })

            new Vue({
                el:"#root"
            })

        </script>

我们查看DOM的时候,一样会发现是没有option标签的,我们也只能使用vue中的is属性

<div id="root">
            <select>
                <option is="row"></option>
                <option is="row"></option>
                <option is="row"></option>
                <option is="row"></option>
            </select>
        </div>

        <script>
            Vue.component("row",{
                template:"<option>1</option>"
            })

            new Vue({
                el:"#root"
            })

        </script>

2.关于组件中的data

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

        <script>
            Vue.component("row",{
                data:{
                    message:"这是一个表格"
                },
                template:"<tr>{{message}}</tr>"
            })

            new Vue({
                el:"#root"
            })
        </script>

这个时候,我们就会发现,页面无法出现数据,而且还报错了,这是什么原因呢?

一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝

也就是说,要是想在组件里面使用data选项,不能够直接写成对象形式,而是一个函数

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

        </div>

        <script>
            Vue.component("row",{
                data:{
                    message:"这是一个表格"
                },
                template:"<tr>{{message}}</tr>"
            })

            new Vue({
                el:"#root"
            })

        </script>

这样子写组件才能正确的显示数据.千万要注意这个问题。

3.关于组件中的 ref
我们来看下vue是怎么操作的页面的DOM元素。vue中操作DOM元素是通过ref这个属性来操作的。

<div id="root">
            <div ref="hello" @click="hand">
                hello
            </div>
        </div>

        <script>
            new Vue({
                el:"#root",
                methods:{
                    hand:function(){
                        console.log(this.$refs.hello)
                    }
                }
            })
        </script>

以上的代码是可以输出div这个DOM元素的,但是这和组件中使用ref有关系吗?我们假设这个div标签是个组件呢?我们来做两个组件相加数值相加的一个功能。

<div id="root">
            <item @change="handC" ref="one"></item>
            <item @change="handC" ref="two"></item>
            <div>{{total}}</div>
        </div>

        <script>
            Vue.component("item",{
                data:function(){
                    return {
                        num:0
                    }
                },
                template:"<div @click='hand'>{{num}}</div>",
                methods:{
                    hand:function(){
                        this.num++
                        this.$emit("change",this.num)
                    }
                }
            })
            new Vue({
                el:"#root",
                data:{
                    total:0
                },
                methods:{
                    handC:function(res){
                        this.total = this.$refs.one.num+this.$refs.two.num
                    }
                }
            })
        </script>

4.父组件向子组件传值

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

父组件通过属性的方式来向子组件传递值,子组件用props来进行接收

<div id="root">
            <item :count="0"></item>
            <item :count="1"></item>
        </div>

        <script>
            var item = {
                props:["count"],
                template:"<div>{{count}}</div>"
            }
            new Vue({
                el:"#root",
                components:{
                    item:item
                }

            })
        </script>

那么我们来进行一个组件的计算,那么就很自然写以下的代码,

<div id="root">
            <item :count="0"></item>
            <item :count="1"></item>
        </div>

        <script>
            var item = {
                props:["count"],
                template:"<div @click='hand'>{{count}}</div>",
                methods:{
                    hand:function(){
                        this.count++
                    }
                }
            }
            new Vue({
                el:"#root",
                components:{
                    item:item
                }

            })
        </script>

这个时候,我们的确是可以点击上面的某个组件让值进行计算,但是我们打开控制台就会发现,就会有报错.为什么呢?因为我们违背vue中”单向数据流”的概念。子组件是不可以直接修改父组件传递过来的值,但有些时候,我们必须要进行修改,怎么办呢?

<div id="root">
            <item :count="0"></item>
            <item :count="1"></item>
        </div>

        <script>
            var item = {
                props:["count"],
                data:function(){
                    return {
                        num:this.count
                    }
                },
                template:"<div @click='hand'>{{num}}</div>",
                methods:{
                    hand:function(){
                        this.num++
                    }
                }
            }
            new Vue({
                el:"#root",
                components:{
                    item:item
                }

            })
        </script>

我们在以上的代码中,在组件中自定义了一个num一个属性,让它等于父组件传递过来的count,那么我们自己修改组件中值是完全没有问题的。

5.子组件向父组件传值
子组件要想向父组件传值,那么就要通过$emit的方法向父组件传值

<div id="root">
            <item :count="0" @change="hanC"></item>
            <item :count="1" @change="hanC"></item>
            <div>{{total}}</div>
        </div>

        <script>
            var item = {
                props:["count"],
                data:function(){
                    return {
                        num:this.count
                    }
                },
                template:"<div @click='hand'>{{num}}</div>",
                methods:{
                    hand:function(){
                        this.num++
                        this.$emit("change",1)
                    }
                }
            }
            new Vue({
                el:"#root",
                data:{
                    total:1
                },
                components:{
                    item:item
                },
                methods:{
                    hanC:function(res){
                        this.total += res
                    }
                }

            })
        </script>

猜你喜欢

转载自blog.csdn.net/Only_ruiwen/article/details/80950815
今日推荐