一、编写可复用的组件
对于需要复用的组件,应当定义一个清晰的公开接口,同时也不需要对其外层数据做出任何假设。
vue组件的api来自三个部分----prop、事件、插槽:
a.prop 允许外部环境传递数据给组件。
b.事件 允许从组件内部触发外部环境的副作用。
c.插槽 允许外部环境将额外的内容组合在组件中。
使用v-bind和v-on的简洁语法,模板的意图会更清晰。
<my-component :foo='baz' :bar='qux' @event-a="doThis" @event-b="doThis">
<img slot="icon" src="..."/>
<p slot="main-text">hellop>
my-component>
二、子组件引用
当需要在javascript中直接访问子组件。为此可以使用ref为子组件制定一个ID:如
<div id="parent">
<child-compoent ref="child">child-compoent>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
<script>
Vue.component('child-compoent',{
template: '子组件
'
});
var parent = new Vue({
el: '#parent',
data: {}
});
var child = parent.$refs.child;
script>
// 当ref和v-for一起使用时,获取到的引用会是一个数组,包含和循环数据源对应的子组件。
// $refs只在组件渲染完成后才填充,并且它是响应式的,它仅仅是一个直接操作子组件的应急方案
// 应当避免在模板或计算属性中使用$refs
三、异步组件
大型应用中,需要将应用拆分成多个小模块,按需从服务器下载。vue允许将组件定义为一个工厂函数,
异步的解析组件的定义。vue只在渲染时触发工厂函数,并把结果缓存起来,用于后面的再次渲染。如:
Vue.component('async-example',function(resolve, reject){
setTimeout(function(){
resolve({template: '异步调用'});
},2000);
});
// 工厂函数接受一个resolve回调,在收到从服务器下载的组件定义时调用。也可以调用reject(reason) 指示加载失败。
四、组件命名约定
当注册组件(或则prop)时,可以使用kebab-case(短横线分割命名),camelCase(驼峰式命名),PascalCase(首字母大写命名)。
在html模块中,camelCase命名要改成kebab-case命名。
当使用字符串模板时,可以不受html大小写不敏感的限制。
五、递归组件
组件在它的模板内可以递归的调用自己,不过,只有当它有name选项时才可以这样做:
<div id="parent">
<Asyncexample>Asyncexample>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
<script>
Vue.component('Asyncexample',{
name: 'example',
template: '递归组件 '
});
var parent = new Vue({
el: '#parent',
data: {}
});
script>
// 这样递归会导致死循环,所以递归是要确保递归调用终止条件。如递归调用时使用v-if并最终解析为false
<div id="parent">
<Asyncexample v-bind:flag="bool">Asyncexample>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
<script>
Vue.component('Asyncexample',{
props:['flag'],
name: 'example',
template: '递归组件 '
});
var parent = new Vue({
el: '#parent',
data: {
bool:false
}
});
script>
六、对低开销的静态组件使用v-once
当组件中包含大量静态内容时,可以使用v-once将渲染结果缓存起来。
Vue.component('Asyncexample',{
template: '大量静态内容'
});
七、边界处理情况
1、访问跟实例
在每个new vue 实例的子组件中,其根实例可以通过$root属性进行访问。如:
<div id="parent">
<my-component v-bind:msg="message">
my-component>
div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js">script>
<script>
Vue.component('my-component',{
props: ['msg'],
template: '',
methods: {
getRootData: function () {
alert(this.$root.root);
}
}
});
var parent = new Vue({
el: '#parent',
data: {
message: '父组件内容',
root: 'hello'
},
methods: {
baz: function () {
、、、
}
}
});
script>
// 所有的子组件都可以讲这个实例作为一个全局store来访问或使用
//获取根实例的数据
this.$root.root;
//写入根实例的数据
this.$root.root = 'hello world';
//调用根实例的方法
this.$root.baz();
2.访问父组件实例
$parent属性可以用来从一个子组件访问父组件的实例,他提供了一种机会,在后期可以随时触达父级组件,
以代替将数据以prop的方法传入子组件的方式。可以使用this.$refs.usernameInput 来访问base-input实例
3.依赖注入
<google-map>
<google-map-region v-bind:shape="cityBoundaries">
<google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map-region>
</google-map>
// 在这个例子中,假如google-map的后代都需要访问一个getMap。那使用$parent属性无法很好的扩展到更深层级的嵌套组件上。
// 这需要依赖注入,它用到了两个新的 实例选项 provide和inject
// provide:允许指定想要提供给后代组件的数据/方法,如:
provide: function () {
return {
getMap: this.getMap
}
}
// 然后在任何后代组件里,都可以使用inject选项来接收指定的我们想要添加在这个实例上的属性,inject:['getMap']
4.程序化的事件侦听器
通过$on(eventName,eventHandler) 侦听一个事件
通过$once(eventName,eventHandler) 一次性侦听一个事件
通过$off(eventName,eventHandler) 停止侦听一个事件