这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战
一、is标签解决模板标签上渲染时出现的小bug
- bug场景:引入子组件时,子组件没有在正确的位置渲染。自定义组件
<row>会被作为无效的内容提升到外部,并导致最终渲染结果出错。如下:
<div id="root">
<table>
<tbody>
<row></row>
</tbody>
</table>
</div>
Vue.component('row',{
template: '<tr><td>This is a table-td</td></tr>'
})
var vm = new Vue({
el: '#root',
})
- 出现问题: 查看后台审查元素,看看页面的渲染情况:发现
<tr>与<table>处于平级,这是不合理的。 因为H5的规范中要求我们将嵌套在中。
- 解决方法:使用is标签在H5标签中使用子组件。
<div id="root">
<table>
<tbody>
<tr is="row"></tr>
</tbody>
</table>
</div>
- 原因分析:Vue在解析 DOM 模板时,有些 HTML 元素,诸如
<ul>、<ol>、<table>和<select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如<li>、<tr>和<option>,只能出现在其它某些特定的元素内部。这就导致用这些有约束条件的元素时遇到上述问题。于是出现了特殊的is属性给了一个变通的办法。
二、子组件中定义的data,值必须为一个函数(函数返回的值为一个对象)
- bug场景:引入子组件时,子组件中直接定义传递内容如下:
Vue.component('row',{
data: {
content: 'This is a test content'
},
template: '<tr><td>{{content}}</td></tr>'
})
-
出现问题:上述代买貌似没有错误,但是页面渲染时会报错。
-
解决方法:子组件定义data时,值必须为一个函数(函数返回一个对象,对象要包含你所对应的数据)。
Vue.component('row',{
data: function(){
return {
content: 'This is a test content'
}
},
template: '<tr><td>{{content}}</td></tr>'
})
- 原因分析:在根组件里(最外层的Vue实例),如果定义data,定义data时,值直接用一个对象,并不会出现什么错误。但如在非根组件中(子组件)定义data时,就不能用一个对象,而是要求data后的值必须为一个函数(函数返回为一个对象)。这是因为子组件在调用时,不像根组件只调用一次,可能会在同一个地方调用多次。每一个子组件在调用时,都应该有自己的数据,而通过一个函数返回一个对象值的目的,就能让每一个子组件都拥有一个独立的数据存储,这样不会有多个子组件互相影响的情况出现。
三、 子组件中 ref 使用的案例,动态获取组件内容
在Vue中一般使用 this.$ref.*** 获取dom节点,来进行dom操作,如 this.$refs.miya.innerHTML,若对动态获取组件内容,应该如何使用呢?
-
场景需求: 制作一个计数器,并且能够点击数字就按顺序+1,并对两个
<counter>组件进行求和; -
解决方法:实现思路如下
-
子组件向父组件发送数据:向外界触发事件(这里用
this.$emit='change')用于告知,即在子组件定义methods使用$emit -
父组件中引用
<counter>组件:用于监听该触发事件,即绑定一个事件监听方法(这里@change="xxx") -
Vue实例定义
methods,使用这个绑定后的方法
<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: function() { return { number: 0 } }, methods: { handleClick: function() { this.number++ //每点击一次,number上的数字就会+1 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 } } }) -