We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
v-modal
v-modal 一般用于表单元素的「数据双向绑定」,对于自定义的 vue 组件,我们也可以通过具体的封装,提供类似 v-modal 的功能,这在封装某些表单组件时会有用。
Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` }) // 使用 <custom-input v-model="searchText"></custom-input>
利用 vue 提供的 <component /> 元素的 is 属性,我们可以实现不同组件的动态切换。
<component />
is
<component v-bind:is="currentTabComponent"></component> // currentTabComponent一般为一个方法,返回对应组件的名称
对于在很多组件中都可能频繁使用的某些基础组件,我们可以给予他们统一格式的命名,然后在应用入口文件中批量全局导入。下面是官方给出的一个示例:
import Vue from 'vue' import upperFirst from 'lodash/upperFirst' import camelCase from 'lodash/camelCase' const requireComponent = require.context( // 其组件目录的相对路径 './components', // 是否查询其子目录 false, // 匹配基础组件文件名的正则表达式 /Base[A-Z]\w+\.(vue|js)$/ ) requireComponent.keys().forEach(fileName => { // 获取组件配置 const componentConfig = requireComponent(fileName) // 获取组件的 PascalCase 命名 const componentName = upperFirst( camelCase( // 剥去文件名开头的 `./` 和结尾的扩展名 fileName.replace(/^\.\/(.*)\.\w+$/, '$1') ) ) // 全局注册组件 Vue.component( componentName, // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先使用 `.default`, // 否则回退到使用模块的根。 componentConfig.default || componentConfig ) })
post: { id: 1, title: 'My Journey with Vue' } <blog-post v-bind="post"></blog-post> // 自组件可以直接获取到props:id,title
大多数情况,外部提供的值会替换掉组件内部的值,不过为了便利,class 和 style 属性不进行合并操作。如果你并不想将不作为 props 识别的属性应用于根元素而想自己指定,那么下面的模式会非常有用:
class
style
props
Vue.component('base-input', { inheritAttrs: false, // 组件的根元素不继承特性 props: ['label', 'value'], template: ` <label> {{ label }} <input v-bind="$attrs" //这里指定属性应用的元素(不包含class,style) v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > </label> ` }) // 使用 <base-input v-model="username" class="username-input" placeholder="Enter your username" ></base-input>
通过 $emit 触发自定义事件,推荐使用连字符命名风格来命名事件(custom-event),有一个很常见的场景是我们需要将 原生的事件绑定到组件上,这需要我们通过 $listeners 来处理:
$emit
custom-event
$listeners
Vue.component('base-input', { inheritAttrs: false, props: ['label', 'value'], computed: { inputListeners: function () { var vm = this // `Object.assign` 将所有的对象合并为一个新对象 return Object.assign({}, // 我们从父级添加所有的监听器 this.$listeners, // 然后我们添加自定义监听器, // 或覆写一些监听器的行为 { // 这里确保组件配合 `v-model` 的工作 input: function (event) { vm.$emit('input', event.target.value) } } ) } }, template: ` <label> {{ label }} <input v-bind="$attrs" v-bind:value="value" v-on="inputListeners" > </label> ` })
这样我们就可以像使用一个普通的 input 标签一样,来使用 <base-input> 组件了。
input
<base-input>
另外,如果你需要一种双向的数据流,可以通过 .sync修饰符来实现:
.sync
<text-document v-bind.sync="doc"></text-document> // doc下所有的属性变化都将是双向的
作用域插槽,提供了从子组件获取数据传入插槽中的方法,这样可以更加灵活地对插槽内容进行控制。
// 子组件 <ul> <li v-for="todo in todos" v-bind:key="todo.id" > <!-- 我们为每个 todo 准备了一个插槽,--> <!-- 将 `todo` 对象作为一个插槽的 prop 传入。--> <slot v-bind:todo="todo"> <!-- 回退的内容 --> {{ todo.text }} </slot> </li> </ul> // 父组件调用 <todo-list v-bind:todos="todos"> <!-- 将 `slotProps` 定义为插槽作用域的名字 --> <template slot-scope="slotProps"> <!-- 为待办项自定义一个模板,--> <!-- 通过 `slotProps` 定制每个待办项。--> <span v-if="slotProps.todo.isComplete">✓</span> {{ slotProps.todo.text }} </template> </todo-list> // slot-scope 目前可以用在任何元素和组件上(不再限制于template)
keep-alive
<!-- 失活的组件将会被缓存!--> <keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>
大型应用中可能需要进行 code-spiltting,那么我们就需要异步加载组件的能力。
code-spiltting
new Vue({ // ... components: { 'my-component': AsyncComponent } }) // 处理加载状态 const AsyncComponent = () => ({ // 需要加载的组件 (应该是一个 `Promise` 对象) component: import('./MyComponent.vue'), // 异步组件加载时使用的组件 loading: LoadingComponent, // 加载失败时使用的组件 error: ErrorComponent, // 展示加载时组件的延时时间。默认值是 200 (毫秒) delay: 200, // 如果提供了超时时间且组件加载也超时了, // 则使用加载失败时使用的组件。默认值是:`Infinity` timeout: 3000 })
类似 React 中 context的作用,父组件提供(provide)方法给所有子组件调用(inject)。
context
provide
inject
// 父组件中 provide: function () { return { getMap: this.getMap } } // 子组件中 inject: ['getMap'] // or inject: { getMap: { from: '指定组件', default: '默认值' } }
组件中往往需要在 beforeDestory 生命周期中清除某些实例(第三方库实例化的对象,定时器,事件绑定等),这导致建立和清理过程是独立的,有时会不便于维护,而利用钩子函数和手动绑定事件监听,我们可以解决这个问题:
beforeDestory
mounted: function () { this.attachDatepicker('startDateInput') this.attachDatepicker('endDateInput') }, methods: { attachDatepicker: function (refName) { var picker = new Pikaday({ field: this.$refs[refName], format: 'YYYY-MM-DD' }) this.$once('hook:beforeDestroy', function () { picker.destroy() }) } }
某些情况下父子组件会出现循环引用的情况,这时候就需要利用异步组件来解决:
components: { TreeFolderContents: () => import('./tree-folder-contents.vue') }
通过 mixins 可以便利地实现某些方法在不同组件中的复用,混入对象可以包含组件的任意选项。对于钩子函数(组件生命周期函数等),混入和组件本身的对应函数都都会执行,混入的会先执行。对于混入和组件本身的数据对象冲突的情况,将会以组件的数据为有限。甚至可以全局混入一个对象,他会对所有的 Vue 实例起作用,应该谨慎使用:
mixins
// 为自定义的选项 'myOption' 注入一个处理器。 Vue.mixin({ created: function () { var myOption = this.$options.myOption if (myOption) { console.log(myOption) } } }) new Vue({ myOption: 'hello!' }) // => "hello!"
directive 在我们需要对底层 Dom 进行操作时会非常有用,一个自定义指令会提供如下几个钩子函数:
directive
bind
inserted
update
componentUpdated
unbind
The text was updated successfully, but these errors were encountered:
naseeihity
No branches or pull requests
Vue 组件
基础
1. 在组件上使用
v-modal
v-modal
一般用于表单元素的「数据双向绑定」,对于自定义的 vue 组件,我们也可以通过具体的封装,提供类似v-modal
的功能,这在封装某些表单组件时会有用。2. 简单的动态组件
利用 vue 提供的
<component />
元素的is
属性,我们可以实现不同组件的动态切换。3. 批量全局注册部分基础组件
对于在很多组件中都可能频繁使用的某些基础组件,我们可以给予他们统一格式的命名,然后在应用入口文件中批量全局导入。下面是官方给出的一个示例:
4. 直接传递一个对象的所有属性
5. 像使用原生 HTML 一样使用基础组件
大多数情况,外部提供的值会替换掉组件内部的值,不过为了便利,
class
和style
属性不进行合并操作。如果你并不想将不作为props
识别的属性应用于根元素而想自己指定,那么下面的模式会非常有用:高级
1. 自定义事件
通过
$emit
触发自定义事件,推荐使用连字符命名风格来命名事件(custom-event
),有一个很常见的场景是我们需要将 原生的事件绑定到组件上,这需要我们通过$listeners
来处理:这样我们就可以像使用一个普通的
input
标签一样,来使用<base-input>
组件了。另外,如果你需要一种双向的数据流,可以通过
.sync
修饰符来实现:2. 插槽
作用域插槽,提供了从子组件获取数据传入插槽中的方法,这样可以更加灵活地对插槽内容进行控制。
3. 动态组件和异步组件
组件切换时保持原先状态
keep-alive
异步组件
大型应用中可能需要进行
code-spiltting
,那么我们就需要异步加载组件的能力。4. 依赖注入
类似 React 中
context
的作用,父组件提供(provide
)方法给所有子组件调用(inject
)。5. 集中式清理代码
组件中往往需要在
beforeDestory
生命周期中清除某些实例(第三方库实例化的对象,定时器,事件绑定等),这导致建立和清理过程是独立的,有时会不便于维护,而利用钩子函数和手动绑定事件监听,我们可以解决这个问题:6. 循环引用
某些情况下父子组件会出现循环引用的情况,这时候就需要利用异步组件来解决:
7. 混入
通过
mixins
可以便利地实现某些方法在不同组件中的复用,混入对象可以包含组件的任意选项。对于钩子函数(组件生命周期函数等),混入和组件本身的对应函数都都会执行,混入的会先执行。对于混入和组件本身的数据对象冲突的情况,将会以组件的数据为有限。甚至可以全局混入一个对象,他会对所有的 Vue 实例起作用,应该谨慎使用:8. 自定义指令
directive
在我们需要对底层 Dom 进行操作时会非常有用,一个自定义指令会提供如下几个钩子函数:bind
进行一次性的初始化,指令第一次绑定到元素时调用inserted
元素被插入父节点时调用update
所在组件的 VNODE 更新时调用componentUpdated
组件及其子组件全部更新后调用unbind
指令与元素解绑时调用The text was updated successfully, but these errors were encountered: