# 文档初探(十): 处理 Edge Cases

# 访问元素&组件

# 访问根实例

Vue.component("sub-1", {
  template: `
  <p>
    {{bar}}
    <button @click="getBaz">get baz</button>
    {{placeholder}}
  </p>`,
  data() {
    return {
      placeholder: 0
    };
  },
  computed: {
    bar() {
      return this.$root.foo;
    }
  },
  methods: {
    getBaz() {
      this.placeholder = this.$root.bar;
      this.$root.baz();
    }
  }
});

new Vue({
  el: "#app",
  template: `
    <div>
      <sub-1 />
    </div>
  `,
  data() {
    return {
      foo: 1
    };
  },
  computed: {
    bar() {
      return "bar";
    }
  },
  methods: {
    baz() {
      alert("你调用了根元素的方法");
    }
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48

# 访问父组件

$root一样, 访问父组件只需要使用$parent.

# 访问子组件

使用$refs访问子组件, 同时要给子组件加上ref属性.

Vue.component("sub-1", {
  template: `
  <p>
    sub-1
  </p>`,
  data() {
    return {
      placeholder: 0
    };
  }
});

new Vue({
  el: "#app",
  template: `
    <div>
      <sub-1 ref="sub"/> <!-- 子组件的ref是sub-->
      <button @click="fetchRefs">获取refs.sub.placeholder</button>
      <p>{{placeholder}}</p>
    </div>
  `,
  data() {
    return {
      placeholder: ""
    };
  },
  methods: {
    fetchRefs() {
      this.placeholder = this.$refs.sub.placeholder; //在这里才可以根据子组件的ref访问到子组件的属性
    }
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

WARNING

$refs只有在所有组件渲染好后才能访问得到, 并且$refs不是响应式的. 它只是作为操纵子组件的备胎方案. 而且必须避免在template里或者在computed属性里访问$refs, 否则都会返回undefined.

# 依赖注入

当父组件的某个状态都被它的子组件和孙子组件们需要, 我们可以使用props, $parent, $root来获取到, 但是这些方法都有一个缺点, 就是需要按照组件的层级关系一层一层往下传递. 如果组件解构很复杂, 那么给后续的维护带来很大的困难. 依赖注入可以让我们跳过层级关系, 让状态直接从提供一方到需要的一方.









 









 
















 
 
 
 
 


Vue.component("son", {
  template: `
    <div style="border: 1px solid red">
      <p>I'm son</p>
      <p>全局状态: {{globalState}}</p>
      <slot></slot>
    </div>
  `,
  inject: ["globalState"]
});

Vue.component("grandSon", {
  template: `
    <div style="border: 1px solid black; width: 50%; margin: 10px">
      <p>I'm grandSon</p>
      <p>全局状态: {{globalState}}</p>
    </div>
  `,
  inject: ["globalState"]
});

new Vue({
  el: "#app",
  template: `
    <div>
      <son>
        <grandSon />
      </son>
    </div>
  `,
  data() {
    return {
      globalState: 1
    };
  },
  provide() {
    return {
      globalState: this.globalState
    };
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41