老实说,阅读文档并不是我们大多数人都喜欢的东西,而是在使用像Vue这样的现代前端框架时,它的不断发展,每个新版本都会改变很多事情,您可能会错过后来引入的一些新的亮点特征,我们看一下那些有趣但不那么流行的功能,这些功能在vue文档中心查到。
在大型应用程序中,可能需要将应用程序分成更小的块,只在需要时从服务器加载组件。为了简化这一过程,Vue允许将组件定义为一个工厂函数,该函数可以异步解析组件定义。Vue只在组件需要呈现时触发工厂函数,并缓存结果以备将来重新呈现。从2.3版开始,新增的功能异步组件工厂函数还可以返回以下格式的对象:
const AsyncComponent = () => ({ // 需要加载的组件 (应该是一个 `Promise` 对象) component: import('./MyComponent.vue'), // 异步组件加载时使用的组件 loading: LoadingComponent, // 加载失败时使用的组件 error: ErrorComponent, // 展示加载时组件的延时时间。默认值是 200 (毫秒) delay: 200, // 如果提供了超时时间且组件加载也超时了, // 则使用加载失败时使用的组件。默认值是:`Infinity` timeout: 3000 })
使用这种方法,可以使用加载和错误状态、组件获取延迟和超时等额外选项。
在Vue中,渲染普通的 HTML 元素是非常快速的,但有的时候可能有一个组件,这个组件包含了大量静态内容。在这种情况下,可以在根元素上添加 v-once
属性以确保这些内容只计算一次然后缓存起来,就像这样:
Vue.component('terms-of-service', { template: ` <div v-once> <h1>Terms of Service</h1> ... a lot of static content ... </div> ` })
再说一次,试着不要过度使用这个模式。当你需要渲染大量静态内容时,极少数的情况下它会给你带来便利,除非你非常留意渲染变慢了,不然它完全是没有必要的——再加上它在后期会带来很多困惑。例如,设想另一个开发者并不熟悉
v-once
或漏看了它在模板中,他们可能会花很多个小时去找出模板为什么无法正确更新。
组件是可以在它们自己的模板中调用自身的。不过它们只能通过 name
选项来做这件事:
name: 'unique-name-of-my-component'
当你使用Vue.component
全局注册一个组件时,这个全局的 ID
会自动设置为该组件的 name
选项。
Vue.component('unique-name-of-my-component', { // ... })
如果不小心,递归组件也可能导致无限循环
name: 'stack-overflow', template: '<div><stack-overflow></stack-overflow></div>'
类似上述的组件将会导致“max stack size exceeded
”错误,所以请确保递归调用是条件性的 (例如使用一个最终会得到 false
的 v-if
)。
当 inline-template
这个特殊的 attribute
出现在一个子组件上时,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。这使得模板的撰写工作更加灵活。
<my-component inline-template> <div> <p>These are compiled as the component's own template.</p> <p>Not parent's transclusion content.</p> </div> </my-component>
内联模板需要定义在 Vue 所属的 DOM 元素内。
不过,
inline-template
会让模板的作用域变得更加难以理解。所以作为最佳实践,请在组件内优先选择template
选项或.vue
文件里的一个<template>
元素来定义模板。
指令的参数可以是动态的。例如,在 v-mydirective:[argument]="value"
中,argument
参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
例如你想要创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以像这样创建一个通过指令值来更新竖直位置像素值的自定义指令:
<div id="baseexample"> <p>Scroll down the page</p> <p v-pin="200">Stick me 200px from the top of the page</p> </div>
Vue.directive('pin', { bind: function (el, binding, vnode) { el.style.position = 'fixed' el.style.top = binding.value + 'px' } }) new Vue({ el: '#baseexample' })
这会把该元素固定在距离页面顶部 200 像素的位置。但如果场景是我们需要把元素固定在左侧而不是顶部又该怎么办呢?这时使用动态参数就可以非常方便地根据每个组件实例来进行更新。
<div id="dynamicexample"> <h3>Scroll down inside this section ↓</h3> <p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p> </div>
Vue.directive('pin', { bind: function (el, binding, vnode) { el.style.position = 'fixed' var s = (binding.arg == 'left' ? 'left' : 'top') el.style[s] = binding.value + 'px' } }) new Vue({ el: '#dynamicexample', data: function () { return { direction: 'left' } } })
对于.passive
、.capture
和.once
事件修饰符,Vue提供了可以与on
一起使用的前缀:
例如:
on: { '!click': this.doThisInCapturingMode, '~keyup': this.doThisOnce, '~!mouseover': this.doThisOnceInCapturingMode }
对于所有其他事件和按键修饰符,不需要私有前缀,因为可以在处理程序中使用事件方法:
有两种方法可以使两个组件在Vue中相互通信,各有各的优缺点。版本2.2中引入的一种新方法是将依赖项注入与Provide / Inject一起使用。
这两个选项一起使用,可以让一个祖先组件成为它所有后代组件的依赖注入器,而不管该组件的层次结构有多深,只要它们在同一个父组件链中。如果您熟悉React,那么这与React的上下文特性非常相似。
// parent component providing 'foo' var Provider = { provide: { foo: 'bar' }, // ... } // child component injecting 'foo' var Child = { inject: ['foo'], created () { console.log(this.foo) // => "bar" } // ... }