文章目录
- 一、深入理解 Vue 组件
- 二、Vue中的动画特效
一、深入理解 Vue 组件
1.1 使用组件容易遇到的坑
总结一些组件再使用时容易遇到的坑:
1.1.1 使用is='组件名'
解决html表签嵌套规范造成的bug
html嵌套规范,会造成bug的标签有table、ul(有的浏览器会)、select等
<div id="app">
<table>
<tbody>
<row></row>
<row></row>
<row></row>
<row></row>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('row',{
template: '<tr><td>这是表格</td></tr>',
});
var vm = new Vue({
el: '#app',
});
</script>
<tr>
标签被渲染到<table>
外面了。
解决方案
<div id="app">
<table>
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('row',{
template: '<tr><td>这是表格</td></tr>',
});
var vm = new Vue({
el: '#app',
});
</script>
1.1.2 非根组件(子组件)中data
必须是函数,返回一个对象。
子组件不像是根组件只会有一个,既然注册了子组件就是想要复用,为了保证每一个子组件数据的唯一性,避免多个子组件数据共享,通过函数将数据存在到独立的函数作用域中。
<div id="app">
<table>
<tbody>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
<tr is="row"></tr>
</tbody>
</table>
</div>
<script type="text/javascript">
Vue.component('row', {
template: "<tr><td @click='addNum'>{
{num}}</td></tr>",
data: function() {
return {
num: 0,
};
},
methods: {
addNum: function() {
this.num++;
},
}
});
var vm = new Vue({
el: '#app',
});
</script>
1.1.3 使用引用ref="引用名"
获取dom元素和组件引用
虽然使用vue我们只需要关心数据,不用操作dom。但是复杂的动画就不要指望vue,还是要使用dom。
1.使用ref获取dom元素
- 通过在html标签上加
ref="xxx"
属性,可通过this.$refs.xxx
取得该dom节点
<div id="app">
<div ref="hello" @click="getDom">{
{message}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data: {
message: ' hello poorpenguin',
},
methods: {
getDom: function(){
console.log(this.$refs.hello);
}
}
});
</script>
2.使用ref获取组件引用
- 在组件上添加了ref属性,可以取得的是该组件的引用(也可以理解为该组件对象),因此可以访问该组件上的属性
这只是举个例子,并不推荐这样写
<div id="app">
<row ref="numOne" @numchange="changeTotal"></row>
+
<row ref="numTwo" @numchange="changeTotal"></row>
= {
{total}}
</div>
<script type="text/javascript">
Vue.component('row',{
template: '<span @click="addNum">{
{number}}</span>',
data: function(){
return {
number: 0,
};
},
methods: {
addNum: function(){
this.number++;
this.$emit('numchange');
}
}
});
var vm = new Vue({
el: '#app',
data: {
total: 0,
},
methods: {
changeTotal: function(){
this.total = this.$refs.numOne.number + this.$refs.numTwo.number;
}
}
});
</script>
两个组件对象。
1.1.4 子组件的单个根元素
当子组件的模板template
中有多个dom元素的时候,要使用一个元素将他们包裹起来。每个组件必须只有一个根元素,所有要将模板的内容包裹在一个父元素内。
模板中这样写是会报错的。
var counter = {
props: ['count'],
template: '<span>123123</span><h1>poorpenguin</h1><div>{
{count}}</div>',
};
这样式正确的写法
var counter = {
props: ['count'],
template: '<div><span>123123</span><h1>poorpenguin</h1><div>{
{count}}</div></div>',
};
1.2 父子组件间的数据传递
1.2.1 父组件传值给子组件
- 父组件通过 属性形式 传值给子组件(不一定要使用
v-bind
将属性和根组件中的变量绑定)
不使用指令v-bind
,直接使用属性进行传值。但是这样" "
中的就不是js表达式,子组件接收到的就是字符串
<div id="app">
<counter count="3"></counter>
</div>
<script type="text/javascript">
var counter = {
props: ['count'],
template: '<div>{
{count}}</div>',
};
var vm = new Vue({
el: '#app',
components: {
'counter': counter,
}
});
</script>
使用指令v-bind
,就可以将属性和根组件中的变量进行绑定,这时" "
中就是js表达式,也可以直接传递数字。
<div id="app">
<counter :count="num1"></counter> 这里使用v-bind命令
或者<counter :count="3"></counter> 这样传递的也是数字,而不是字符串
</div>
<script type="text/javascript">
var counter = {
props: ['count'],
template: '<div>{
{count}}</div>',
};
var vm = new Vue({
el: '#app',
data: {
num1: 3,
},
components: {
'counter': counter,
}
});
</script>
- 子组件通过
props[]
接收传递过来的属性,但是不能直接操作接收的属性。
子组件通过props[]
接收传递过来的属性,并将传递过来的属性赋值给在data
中定义新属性。
因为单项数据流,修改Object的值会导致别的引用了该对象的子组件内数据的变化,用在子组件内复制一份该对象,修改子组件内自己的data来代替。
<div id="app">
<counter :count="num1"></counter>
</div>
<script type="text/javascript">
var counter = {
props: ['count'],
data: function(){
return {
number: this.count,
};
},
template: '<div @click="addNum">{
{number}}</div>',
methods: {
addNum: function(){
this.number++
},
}
};
var vm = new Vue({
el: '#app',
data: {
num1: 3,
},
components: {
'counter': counter,
}
});
</script>
错误示范:
子组件
var counter = {
props: ['count'],
template: '<div @click="addNum">{
{count}}</div>',
methods: {
addNum: function(){
this.count++
},
}
};
1.2.2 子组件传值给父组件
- 子组件事件触发的形式
this.$emit("自定义事件名","传给父组件的数据"),
向父组件传值
var counter = {
props: ['count'],
data: function(){
return {
number: this.count,
};
},
template