踩坑小结2

1. 路由

1.1 跳转页面

开发中遇到需要在函数中实现页面跳转时,一般会使用this.$router.push。

使用 创建 a 标签来定义导航链接时,我们点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。

那么若想要跳转时新开一个页面,而不是在原有页面中跳转,这时可以通过添加target=_blank属性:

1
<router-link target="_blank" :to="home">新页面打开home页</router-link>

编程式导航需要使用this.$router.resolve:

1
2
let routeData = this.$router.resolve({ path: '/home', query: { id:id }});
window.open(routeData.href, '_blank');

1.2 路由传参

既然涉及到传参,也简单说明一下。
首先要清楚

this.$router:VueRouter 实例,有一系列对应的方法:router.push、 router.replace 和 router.go等。

this.$route:当前激活的路由信息对象。这个属性是只读的,里面的属性是 immutable (不可变) 的,不过你可以 watch (监测变化) 它,可以获取name、path、query、params等。

vue-router传参一般使用的是query和params,分别介绍两种方式。

1.2.1query方式传参和接收参数

1
2
3
4
5
6
7
8
9
10
传参: 
this.$router.push({
path:'/xxx',
query:{
id:id
}
})

接收参数:
this.$route.query.id

如果提供了path,params会被忽略:

1
2
3
4
5
6
7
this.$router.push({
path: '/xxx',
params: {
id:id
}
})
// 这里的 params 不生效

1.2.2params方式传参和接收参数

1
2
3
4
5
6
7
8
9
10
传参: 
this.$router.push({
name:'xxx',
params:{
id:id
}
})

接收参数:
this.$route.params.id

手写完整的带有参数的 path:

1
this.$router.push({ path: `/xxx/${id}` })

同样可以结合_blank新开页面传递参数,这里上面已经有示例了。

另外,使用query传参页面跳转的时候,可以在地址栏看到请求参数,而params传参时不会在地址栏中显示。

1.3 路由模式

最后还有一点,我觉得url上的#不好看想去掉于是设置了history模式,结果!!!!!跳转时新开页面报错404,在本地开发的时候没有问题,放到服务器上就报错,找了很久问题所在…………直到看了官方文档说是后端也需要配置,果然文档需要仔细看啊。以前觉得history就是用来去掉那个难看的#的,其实里面学问还挺多的。

2. 父子组件通信

父组件传入子组件的prop中的值是不允许改变的。

我是在父组件传递给子组件分页的当前页currentPage时遇到的,翻页的时候会触发事件给父组件,父组件在自己的方法中改变后再传递给子组件,但是子组件也触发了修改currentPage的事件想要修改props中的值。

报错:[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “currentPage” (found in component)

2.1 中间变量

一种方法用中间值替代:在data中使用一个中间变量,将其赋值为props的值,所有操作props值得地方都通过操作data中副本来实现,对父组件不做改变。

1
2
//父组件HTML
<TableData :tableData="tableData" :currentPage.sync="currentPage" :total="total" :nextPage="nextPage" @handleCurrentChange="handleCurrentChange"></TableData>
1
2
3
4

//子组件HTML
<el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="10" layout="total, prev, pager, next, jumper" :total="total">
</el-pagination>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

<!--子组件JS-->
export default {
name: 'TableData',
props: {
pcurrentPage: {
type: Number,
default: 1
}
},
data(){
return{
currentPage:this.pcurrentPage
}
}
...

}

2.2 .sync修饰符

还可以使用.sync修饰符

再次说明,要好好读文档。

3. filter与slot使用姿势

https://segmentfault.com/q/1010000015780925

过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。

1
2
3
4
5
<!-- 在双花括号中 -->
{{ message | capitalize }}

<!-- 在 `v-bind` 中 -->
<div v-bind:id="rawId | formatId"></div>

这次遇到的是对table中的某个单元格进行过滤,并定义点击事件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<el-table-column  prop="data" label="data" align="center">
<template slot-scope="scope">
<span @click="somethingtodo(scope.row)">{{scope.row.data|replacena}}</span>
</template>
</el-table-column>

methods:{
somethingtodo(row) {
...
}
},

filters: {
replacena(value) {
if(value==''){
return '空'
}else{
return value
}
},
}

在2.6.0中,我们为具名插槽和作用域插槽引入了一个新的统一的语法(即v-slot指令。它取代了slot和slot-scope这两个目前已被废弃但未被移除且仍在文档中的特性。