Fork me on GitHub

vue2.0 踩坑记

frontend/vuejs/attention/vue_attention_logo

自己接触vuejs将近一年,在这段时间里面,一共参与了公司以vuejs技术为框架的两个项目—-工单系统(公司内部项目,不方便贴链接)和淘米淘手游交易平台移动端(未上线)。本文是自己在使用vuejs开发过程中踩到的坑,特此记录下来的文章。嗯,希望对相关的技术爱好者有所帮助啦(如果你知道我在讲什么的话) 😊

对了,在开始写文章之前,先说明下: 文章里面的代码,是在.vue后缀的文件中实现的,在脚手架vue-cli搭建的项目上已经验证过,如有疑问,请自行验证或者在文章底部留言功能那里留言(仅支持github账号用户),或者邮箱留言(1837895991@qq.com)哦。

父组件传递消息给子组件

使用props,下面先来看一个简单的例子:

父组件: parent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div id="parent">
<child-component :title='parentTitle' />
</div>
</template>
<script>
import childComponent from '@/components/path/to/childComponent.vue'
export default {
data () {
return {
parentTitle: 'title form parent'
}
},
components: {
childComponent
}
}
</script>
<style scoped>
#parent{}
</style>

子组件: childComponent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div id="child">
<h1>{{title}}</h1>
</div>
</template>
<script>
export default {
data () {
return {

}
},
props: {
title: {
type: String, // 可设置类型
default: 'title from child' // 默认值
}
}
}
</script>
<style scoped>
#child{}
</style>

最后显示的结果是父亲传过来的消息,即信息为title form parent的h1标题。在父组件向子组件传递消息的过程中,首先,父亲需要拿到子组件<child-component />,然后告诉子组件我要传递一个title给你:title='parentTitle',注意查收。接着,子组件通过props新建一个title的属性,并将数据读取到数据填充到相应的位置。详情看官网Prop

子组件传递消息给父组件

子组件是通过$emit向父组件发送事件和相关的数据,来传递信息给父组件。

子组件(child.vue)的demo代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div id="child">
<button @click="toParent">向父组件传递消息</button>
</div>
</template>
<script>
export default {
name: "child",
data () {
return {
message: 'message from children'
}
},
methods: {
toParent () {
var vm = this;
vm.$emit('child-say',vm.message);
}
}
}
</script>

父组件demo代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<template>
<div id="parent">
<child-component @child-say="parentEvent" />
<h1>{{msg}}</h1>
</div>
</template>
<script>
import childComponent from '@/components/path/to/child.vue';
export default {
name: 'parent',
data () {
return {
msg : ''
}
},
methods: {
parentEvent: function (data) { // data 是子组件传过来的数据
var vm = this;
vm.msg = data;
}
},
components: {
childComponent
}
}
</script>

上面代码的过程是,点击了子组件里面的向父组件传递消息的按钮,将子组件里面的message信息放在$emit里面发送给父组件,而父组件在引用的子组件中新建一个事件来接受传过来的信息,然后在父组件中创建的方法对data里面的msg进行数据的改写。最终在页面上显示出的h1标题信息为message from children,即是子组件里面的信息。嗯,官网相关传送门

通过原型组件信息传递

在组件的信息传递中,可以通过构造函数和实例之间的原型链来实现。如下:

1
2
3
4
5
6
import Vue from 'vue'

// 注册一个中央事件总线,代替vuex
Vue.prototype.bus = new Vue();
// 全局存储对象
Vue.prototype.bus.global = {}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
methods: {
async getBaziData() {
const rsp = await requestBazi();
this.baziData = res;
this.bus.global.baziData = res;
},
alreadyRequest(type) {
if(this.bus.global.baziData) {
this.baziDetail = this.bus.global.baziData[type];
this.articleCatId = this.bus.global.baziData.config[type]
return true;
}
return false;
}
}

使用vuex

使用vuex来进行组件间的数据通信,详情请看我写的文章,请戳vuex要点

绑定HTML Class

类名结合style的使用一般是用来动态改变样式,所以要用到v-bind:class
简写:class

demo如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<button class="default-bg" :class="{'active-bg':flag}" @click="changeBtnBg">按钮</button>
</template>
<script>
export default {
data () {
return {
flag : false
}
},
methods: {
changeBtnBg: function () {
vm.flag = true;
}
}
}
</script>
<style scoped>
.default-bg{
background: red;
}
.active-bg{
background: blue;
}
</style>

上面代码中,实现了一个红色按钮通过点击自身实现变成绿色按钮的功能。首先,自己给到一个默认的红色的按钮,并且在按钮上绑定了changeBtnBg的方法,用于控制标志符flag的布尔值。值得注意的是,:class通过flag的真假值来决定是否改变按钮的背景色为定义的绿色。官网相关请戳这里

v-model引用的数据需初始化

也许你遇到这个问题,命名写了<input type="text" v-model="inputMsg" />,可是相关的数据绑定<div></div>却没有消息,并报错。这是因为你还没有初始化相关的数据啊。正确的姿势应该像下面👇

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<input type="text" v-model="inputMsg"/>
<div>{{inputMsg}}<div>
</template>
<script>
export default {
data () {
return {
inputMsg : '' // 记得初始化数据哦
}
}
}
</script>

style中的scoped

也许你注意到了我上面的代码中,在每个<style><style>的元素中添加了scoped。scoped是用来限定样式的作用的范围,防止此组件里面的样式和其他组件的同名的样式产生冲突。比如—-

component1.vue

1
2
3
4
5
6
7
8
<template>
<h1 id = "title">component1's title</h1>
</template>
<style scoped>
#title{
color: red;
}
</style>

component2.vue

1
2
3
4
5
6
7
8
<template>
<h1 id="title">component2's title</h1>
</template>
<style scoped>
#title{
color: blue;
}
</style>

在上面的两个组将component1.vue && component2.vue中,虽然都有相同的id,但是对各自没什么影响。简单说,加上scoped之后,样式的编写只对本组件有效。

watch监听数据

在数据发生改变的时候,需要监听数据做到动态修改数据,就要使用到watch了,这里分为普通监听和深度监听,直接看demo啦。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script>
export default {
data(){
msg: 'init msg',
obj: {
arr: [1,2,3],
name: '嘉明'
}
},
watch: {
// 普通监听
msg(newVal , oldVal){
console.log("msg:" + newVal , oldVal);
},
// 深度监听,可以监听到对象、数组的变化
obj: {
handler(newVal , oldVal){
console.log("obj.arr" + newVal , oldVal);
// 相关处理
// ...
},
deep: true
}
}
}
</script>

@clcik/@mouseover等方法失效问题

在使用一些整合了vue的ui框架的时候,比如使用element-ui,在其封装的标签上写一些方法的时候,通常是不会生效的(当然你可以使用他们封装好的方式去使用),可是在没有合适的方式的时候,想使用原来的@clcik怎么办?

下面的代码说明问题,在@click后面添加一个native属性就行,即是@click.native,其他的方法类似。

1
2
3
4
5
# click无效代码
<el-col @click="alert('click')" :span="24">click me</el-col>

# click有效代码
<el-col @click.native="alert('click')" :span="24">click me</el-col>

精力有限,未能一次性更新完,忘见谅…

<-- 本文已结束  感谢您阅读 -->
客官,且步,赏一个呗 (@ ~ @)