不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式。
如果你希望父组件的 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,可以使用深度选择器: >>> 操作符。
<style scoped> .a >>> .b { /* ... */ } </style>
上述代码将会编译成:
.a[data-v-f3f3eg9] .b { /* ... */ }
但是,有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 或 ::v-deep 操作符,这两者都是 >>> 的别名,实现同样的功能。
我们都知道,通过 v-html 创建的 DOM 内容不受 scoped 样式影响,可以通过深度作用选择器>>>来为他们设置样式。
七、路由的props属性
一般在组件内使用路由参数,大多数人会这样做:
export default { methods: { getParamsId() { return this.$route.params.id } } }
当你随便用用,临时凑手,这没什么问题,毕竟解决了需求。
可我们要随时谨记:组件是用来复用的!组件应该有高度的封闭性!
在组件中使用 $route 会使它与路由系统形成高度耦合,从而使组件只能在使用了路由功能的项目内,或某些特定的 URL 上使用,限制了其灵活性。
试想一下,如果你的组件被人拿去复用了,但是那个人并没有使用路由系统,而是通过别的方式传递id参数,那么他该怎么办?
正确的做法是通过 props 解耦!
首先,为组件定义一个叫做id的prop:
export default { props: ['id'], methods: { getParamsId() { return this.id } } }
如果组件没有对应路由,那么这个id也可以通过父组件向子组件传值的方式使用。
如果使用了路由,可以通过路由的prop属性,传递id的值:
const router = new VueRouter({ routes: [{ path: '/user/:id', component: User, props: true }] })
将路由的 props 属性设置为 true 后,组件内可通过 props 接收到 params 参数
另外,你还可以通过函数模式来返回 props
const router = new VueRouter({ routes: [{ path: '/user/:id', component: User, props: (route) => ({ id: route.query.id }) }] })
其实,上面的技巧,在VueRouter的官档都有说明。
八、异步组件
在大型应用中,我们可能需要将应用分割成小一些的代码块,并且只在需要的时候才从服务器加载一个模块。
为了简化,Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。Vue 只有在这个组件需要被渲染的时候才会触发该工厂函数,且会把结果缓存起来供未来重渲染。例如:
Vue.component('async-example', function (resolve, reject) { setTimeout(function () { // 向 `resolve` 回调传递组件定义 resolve({ template: '<div>I am async!</div>' }) }, 1000) })
如你所见,这个工厂函数会收到一个 resolve 回调,这个回调函数会在你从服务器得到组件定义的时候被调用。
你也可以调用 reject(reason) 来表示加载失败。这里的 setTimeout 是为了演示用的,如何获取组件取决于你自己。
一个推荐的做法是将异步组件和 webpack 的 code-splitting 功能一起配合使用: