8Vue组件使用细节

1.table中使用组件

我们写一个表格table代码

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="./vue.js"></script>
  <title>Document</title>
</head>
<body>
  <div id="app">
    <table>
      <tbody>
        <row></row>
        <row></row>
        <row></row>
      </tbody>
    </table>
  </div>
</body>
<script>
  Vue.component('row',{
    template:"<tr><td>this is a row</td></tr>"
  })
  var vm=new Vue({
    el:"#app",
   
  })
</script>
</html>

渲染效果如下:

 

 

 看似没有问题,但是当我们将控制台打开,就能发现有不对的地方了

 

 

 tr和table居然在同级,这违反了HTML5的规范。要解决这个问题,我们可以使用“is”,来指定组件。

如下修改:

<table>
      <tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
      </tbody>
    </table>

意思是tobody中的tr是row组件,这样既可以使用我们的组件,又可以符合HTML5的规范。控制台中的结构也是正确的。

 

 

 同理,ul、ol、select这些元素在直接嵌入组件也可能会出现上面的Bug。

 

2.组子件中的data

在前面代码的基础上,我们将row组件内容修改一下,如下:

Vue.component('row',{
    data:{
      content:"this is row"
    },
    template:"<tr><td>{{content}}</td></tr>"
  })
  var vm=new Vue({
    el:"#app",
   
  })

主要就是将文本内容抽出来做数据。

然后发现这种做法会报错,内容如下图:

 

 

 这是因为,在非根组件的组件中使用data,需要用一个函数来返回data的内容,内容是一个对象,修改如下:

Vue.component('row',{
    data:function(){//一个函数
      return {
        content:'this is content'
      }
    },
    template:"<tr><td>{{content}}</td></tr>"
  })

这样设计的目的就是为了子组件在复用的时候,data内的数据不会相互影响,所以通过函数返回的方式,保证每一个子组件有独立的数据存储。

 

完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="./vue.js"></script>
  <title>Document</title>
</head>
<body>
  <div id="app">
    <table>
      <tbody>
        <tr is="row"></tr>
        <tr is="row"></tr>
        <tr is="row"></tr>
      </tbody>
    </table>
  </div>
</body>
<script>
  Vue.component('row',{
    data:function(){
      return {
        content:'this is content'
      }
    },
    template:"<tr><td>{{content}}</td></tr>"
  })
  var vm=new Vue({
    el:"#app",
   
  })
</script>
</html>

3.组件使用ref

有些时候我们会写比较复杂的动画,操作DOM的行为就可能无法避免了,我们可以使用ref来获取dom,如下:

<div id="app">
    <div
      ref='hello'
      @click="handleClick"
    >
      hello!
    </div>
var vm=new Vue({
    el:"#app",
    methods:{
      handleClick:function(){
        //this.$ref是所有ref的集合
        console.log(this.$refs.hello)
        alert('hello')
      }
    }
  })

 

我们通过给div标签设置ref,并取名为hello,然后通过this.$refs.hello就可以获取到这个div的dom

 

 但是如果ref设置在一个组件上呢?

比如我们现在需要做两个计数器,点击一下就会加1,然后还有一个求和,如下:

<body>
  <div id="app">
    <counter></counter>
    <counter></counter>
    <div>{{total}}</div>
  </div>
</body>
  Vue.component('counter',{
    template:'<div @click="handleClick">{{number}}</div>',
    data:function(){
      return {
        number:0
      }
    },
    methods:{
      handleClick:function(){
        this.number++;
      }
    }
  })
  var vm=new Vue({
    el:"#app",
    data:{
      total:0
    }
  })

 

 现在实现的功能还只能计数,不能求和。我们也可以使用ref来获取组件中的值

 <div id="app">
    <!-- 子组件触发change,父组件监听,触发handleChange方法 -->
    <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:function(){
      return {
        number:0
      }
    },
    methods:{
      handleClick:function(){
        this.number++;
        //触发change方法
        this.$emit('change')
      }
    }
  })
  var vm=new Vue({
    el:"#app",
    data:{
      total:0
    },
    methods:{
      handleChange:function(){
        //this.$refs.one、this.$refs.two获取到的是组件的引用
        console.log(this.$refs.one);
        console.log(this.$refs.two);
        this.total=this.$refs.one.number+this.$refs.two.number;
      }
    }
  })

打印结果如下

 

 

this.$refs.one、this.$refs.two获取到的是组件的引用,而不是dom

 

渲染出来的结果:

 

 完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="./vue.js"></script>
  <title>Document</title>
</head>
<body>
  <div id="app">
    <!-- 子组件触发change,父组件监听,触发handleChange方法 -->
    <counter ref="one" @change="handleChange"></counter>
    <counter ref="two" @change="handleChange"></counter>
    <div>{{total}}</div>
  </div>
</body>
<script>
  Vue.component('counter',{
    template:'<div @click="handleClick">{{number}}</div>',
    data:function(){
      return {
        number:0
      }
    },
    methods:{
      handleClick:function(){
        this.number++;
        //触发change方法
        this.$emit('change')
      }
    }
  })
  var vm=new Vue({
    el:"#app",
    data:{
      total:0
    },
    methods:{
      handleChange:function(){
        //this.$refs.one、this.$refs.two获取到的是组件的引用
        console.log(this.$refs.one);
        console.log(this.$refs.two);
        this.total=this.$refs.one.number+this.$refs.two.number;
      }
    }
  })
</script>
</html>

 

posted @ 2020-12-08 16:47  ellenxx  阅读(85)  评论(0编辑  收藏  举报