Vue 中组件使用中的细节点

框架

浏览数:52

2019-2-12

AD:百G视频免费分享

is标签

如何使用is标签解决渲染中可能会出现的小bug

<div id="root">
    <table>
        <tbody>
            <row></row>
            <row></row>
            <row></row>
        </tbody>
    </table>
</div>
Vue.component('row',{
    template:'<tr><td>this is a row</td></tr>'
})
let vm = new Vue({
    el: '#root'
})

正常渲染一个组件这样写没有啥问题,但是在table中会有点小bug,如下图

正常来说3个tr应该在tbody里面,而现在和table同级了,这是怎么回事呢?

html5规范中,tbody里面必须是tr标签,否则会出错。该怎么解决呢?看下面代码

<div id="root">
    <table>
        <tbody>
            <tr is="row"></tr>
            <tr is="row"></tr>
            <tr is="row"></tr>
        </tbody>
    </table>
</div>
Vue.component('row',{
    template:'<tr><td>this is a row</td></tr>'
})
let vm = new Vue({
    el: '#root'
})

这段代码是什么意思呢?,意思是:tbody里面我要用一个组件,但我不能直接使用组件,所以我就写了一个tr,我用is表示,虽然这里写的是tr,但实际上它是名为row的组件。这样写,既能保证tr里面显示的使我们的组件,又能保证它符合html5的规范,程序就不会有bug了。如下图所示:

is标签就变成了我们想要展示的效果了。is标签还可以用在ulolselect标签中。

组件中的数据存储

在根组件里面,我直接要定义data,可以直接定义成对象的形式,不会有任何的问题。

但是当你在非根组件中子组件里去定义data,就不能直接定义成对象了,data的定义就必须要求,后面的值必须是一个函数。同时这个函数要求返回一个对象,这个对象里面要包含你所要的数据。

data(){
    return {
        content: 'this is content'
    }
}

在子组件里面定义data的时候,data必须是个函数,而不能是个对象,之所有这么设计是因为一个子组件不像根组件只会被调用一次,每一个子组件,它的数据我不希望和其他子组件的数据产生冲突,或者说每一个子组件都应该有自己的数据,而不是和其他组件共享数据。通过一个函数来返回一个对像的目的,就让每一个子组件都拥有一个独立的数据存储,这样就不会出现多个子组件之间互相影响的情况。

ref引用

我们说 Vue 不建议我们直接在代码中操作dom,但是在处理一些极其复杂的动画效果时,你不操作dom,刚靠 Vue 这种数据绑定。有些时候处理不了这样的情况,所以在某些必要的情况下,还真就得操作dom,那么在 Vue 之中如何处理dom呢?

<div id="root">
    <div ref="hello" @click="handleClick"></div>    // ref="hello"
</div>
<script>
    let vm = new Vue({
        el: '#root',
        methods: {
            handleClick(){
                console.log('hello world')
               this.refs.hello              //点击时获取 
            }
        }
    })

我给这个div起一个名字ref的名字叫做hello,然后在handleClick上就可以获取到它了。

那要是ref写在组件上,获取到的应该是什么呢?

<div id="root">
    <counter ref="one" @change="handleChange"></counter>    //组件中监听事件
    <counter ref="two" @change="handleChange"></counter>
    <div>{{total}}</div>
</div>
Vue.component('counter', {
    template: '<div @click="handleClick">{{number}}</div>',
    data() {
        return {
            number: 0
        }
    },
    methods: {
        handleClick(){
            this.number ++
            this.$emit('change')        //number 改变时,触发 change 事件
        }
    }
})
let vm = new Vue({
    el: '#root',
    data:{
        total: 0
    },
    methods: {
        handleChange() {
            this.total = this.$refs.one.number + this.$refs.two.number
        }
    }
})

当我点击组件时,handleClick会被触发,number会被改变,number改变时,用this.$emit触发change事件,counter组件中监听change事件,this.$refs.名字获取对应的组件,并相加,就能得到最后的total

当它写在div这样一个标签上的时候,this.$refs.名字时获取到的是标签对应的dom元素,而当你在一个组件上去写ref然后通过this.$refs.名字时获取到的是对应子组件的引用。

原文地址:https://segmentfault.com/a/1190000018120316

相关推荐