通常情况下我们在组件内获取路由参数的办法是:
1export default { 2 computed: { 3 paramsId () { 4 return this.$route.params.id 5 } 6 } 7}
在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。 正确的做法是通过 props 解耦
1const router = new VueRouter({ 2 routes: [{ 3 path: /user/:id , 4 component: User, 5 props: true 6 }] 7})
将路由的 props 属性设置为 true 后,组件内可通过 props 接收到 params 参数
1export default { 2 props: [ id ] 3}
另外还可以通过函数模式来返回 props
1const router = new VueRouter({ 2 routes: [{ 3 path: /user/:id , 4 component: User, 5 props: (route) => ({ 6 id: route.query.id 7 }) 8 }] 9})
函数式组件是无状态,它无法实例化,没有任何的生命周期和方法。创建函数式组件也很简单,只需要在模板添加 functional 声明即可。一般适合只依赖于外部数据的变化而变化的组件,因其轻量,渲染性能也会有所提高。 组件需要的一切都是通过 context 参数传递。它是一个上下文对象,具体属性查看文档。这里 props 是一个包含所有绑定属性的对象。 函数式组件
1<template functional> 2 <div class="list"> 3 <div class="item" v-for="item in props.list" :key="item.id" @click="props.itemClick(item)"> 4 <p>{{item.title}}</p> 5 <p>{{item.content}}</p> 6 </div> 7 </div> 8</template>
父组件使用
1<template> 2 <div> 3 <List :list="list" :itemClick="item => (currentItem = item)" /> 4 </div> 5</template> 6import List from @/components/List.vue 7export default { 8 components: { 9 List 10 }, 11 data() { 12 return { 13 list: [{ 14 title: title , 15 content: content 16 }], 17 currentItem: null 18 } 19 } 20}
在开发中修改第三方组件样式是很常见,但由于 scoped 属性的样式隔离,可能需要去除 scoped 或是另起一个 style 。这些做法都会带来副作用(组件样式污染、不够优雅),样式穿透在css预处理器中使用才生效。 我们可以使用 >>> 或 /deep/ 解决这一问题:
1<style scoped> 2外层 >>> .el-checkbox { 3 display: block; 4 font-size: 26px; 5 6 .el-checkbox__label { 7 font-size: 16px; 8 } 9} 10</style> 11<style scoped> 12/deep/ .el-checkbox { 13 display: block; 14 font-size: 26px; 15 16 .el-checkbox__label { 17 font-size: 16px; 18 } 19} 20</style>
通常我们监听组件生命周期会使用 $emit ,父组件接收事件来进行通知 子组件
1export default { 2 mounted() { 3 this.$emit( listenMounted ) 4 } 5} 6// 父组件 7<template> 8 <div> 9 <List @listenMounted="listenMounted" /> 10 </div> 11</template>
其实还有一种简洁的方法,使用 @hook 即可监听组件生命周期,组件内无需做任何改变。同样的, created 、 updated 等也可以使用此方法。
1<template> 2 <List @hook:mounted="listenMounted" /> 3</template>
在页面挂载时定义计时器,需要在页面销毁时清除定时器。这看起来没什么问题。但仔细一看 this.timer 唯一的作用只是为了能够在 beforeDestroy 内取到计时器序号,除此之外没有任何用处。
1export default { 2 mounted() { 3 this.timer = setInterval(() => { 4 console.log(Date.now()) 5 }, 1000) 6 }, 7 beforeDestroy() { 8 clearInterval(this.timer) 9 } 10}
如果可以的话最好只有生命周期钩子可以访问到它。这并不算严重的问题,但是它可以被视为杂物。 我们可以通过 $on 或 $once 监听页面生命周期销毁来解决这个问题:
1export default { 2 mounted() { 3 this.creatInterval( hello ) 4 this.creatInterval( world ) 5 }, 6 creatInterval(msg) { 7 let timer = setInterval(() => { 8 console.log(msg) 9 }, 1000) 10 this.$once( hook:beforeDestroy , function() { 11 clearInterval(timer) 12 }) 13 } 14}
使用这个方法后,即使我们同时创建多个计时器,也不影响效果。因为它们会在页面销毁后程序化的自主清除。