十五、处理边界情况

处理边界情况

(1.)访问元素&组件

大多数情况下,不要触达另一个组件实例内部或手动操作DOM元素。不过有些情况下是可以的。

  • (1.)访问根实例:在每个new Vue实例的子组件中,根实例可以通过$rootproperty进行访问。所有的子组件都可以将这个实例作为一个全局的store来访问或使用。
new Vue({
	data: {
		foo: 1
	},
	computed: {
		bar:function() {...}
	},
	methods: {
		baz: function() {...}
	}
})
this.$root.foo   // 子组件获取根组件的数据
this.$root.foo = 2  // 写入根组件的数据
this.$root.bar   // 访问根组件的计算属性
this.$root.baz()  // 调用根组件的方法

对于demo或非常小型的少量组件的应用来说很方便,在大型项目里推介Vuex来管理应用状态。

  • (2.)访问父组件实例:与$root类似,$parentproperty可用来从一个子组件访问父组件的实例。可以在后期随时触达父级组件,来替代将数据与prop方式传入子组件方式。
  • (3.)$root$parent的不同: r o o t 与 root与 rootparent都可以实现访问父组件的属性和方法。不同是如果存在多级子组件,$parent访问得到的是离它最近的父组件,$root访问的则是根组件。例:
<google-map>
<!--google-map可以定义一个map property,google-map-markers可以通过this.$parent.getMap的方式来访问-->
	<google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
</google-map>

<google-map>
<!--当在google-map-markers外层再加一层新的组件,这时再去访问则需要用this.$parent.$parent.map来访问-->
  <google-map-region v-bind:shape="cityBoundaries">
    <google-map-markers v-bind:places="iceCreamShops"></google-map-markers>
  </google-map-region>
</google-map>
  • (4.)使用$ref访问子组件实例或子元素:尽管存在事件和prop,有时仍需要在javascript里直接访问一个子组件,可以通过ref这个属性为子组件赋予一个ID引用。例:
<base-input ref="usernameInput"></base-input>

在已经定义这个ref的组件的组件里,可以使用:this.$refs.usernameInput来访问这个<base-input>实例。
甚至可以通过父级组件定义方法,例:

methods: {
  // 用来从父级组件聚焦输入框
  focus: function () {
    this.$refs.usernameInput.focus()
  }
}

整个完整实例:

<div id="app">
			<!--此处为子组件加ref-->
            <component-three ref="usernameInput"></component-three>
            <button @click="clickFocus">心情按钮</button>
        </div>
        <template id="componentC">
            <p>{{ msg }}</p>
        </template>
        <script>
            Vue.component('component-three',{
                template: `<p>{{ msg }}</p>`,
                data:function(){
                    return {
                        msg: '今天过得怎么样?'
                    }
                },
                methods: {
                    focus () {
                       this.msg = "今日心情:还可以。"
                    }
                }
            })
            var vm = new Vue({
                el:"#app",
                methods:{
                    clickFocus (){
                    	//  通过this.$ref.xxx执行子组件方法
                        this.$refs.usernameInput.focus()
                    }
                }
            })
        </script>
  • (5.)依赖注入:在使用$parent访问父级组件实例时发现在存在多层子组件时,$parent无法进入更深层次的嵌套组件上,容易引发混乱。依赖注入可以很好地解决这个问题。
  • 依赖注入用到了两个新的实例选项:provideinject
  • provide选项允许我们指定想要提供给后代组件的数据/方法,例:
provide: function () {
  return {
    getMap: this.getMap   // 想要提供给后代的方法/数据
  }
}
  • 在后代组件中使用inject选项接收指定我们想要添加在这个实例上的属性,例:
inject: ['getMap']
(2.)程序化的事件侦听器

$emit可以被v-on侦听,Vue实例同时在其事件接口中提供了其他方法。

  • 通过$on(eventName,eventHandler) 侦听一个事件
  • 通过$once(eventName,eventHandler) 一次性侦听一个事件
  • 通过$off(eventName,eventHandler) 停止侦听一个事件
(3.)循环引用
  • (3.1)递归组件:组件可以在它们自己的模板中调用自身,不过只能通过name选项来做这件事,例:
name:'unique-name-of-my-component'
  • (3.1.1)当使用Vue.component全局注册一个组件时,这个全局的ID会自动设置为该组件的name选项。
name: 'stack-overflow',
template: '<div><stack-overflow></stack-overflow></div>'
  • (3.1.2)上述组件会导致’max stack size exceeded’错误,必须确保递归调用是条件性的。
  • (3.2)组件之间的循环引用:
(4.)模板定义替代品
  • (1.)内联模板:当inline-template这个属性出现在一个子组件上时,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。例:
<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>
(5.)控制更新
  • (1.)强制更新:$forceUpdate
  • (2.)v-on创建低开销静态组件:当有个包含大量静态内容的组件,你可以在根元素上添加v-once,确保这些内容只计算一次然后缓存起来。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值