Vue 组件(七)

1、组件创建及使用

(1)在 components 目录下,新建 Learn.vue 文件,示例代码如下:

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <p>hello world</p>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {

    }
}
</script>

<!-- 样式,scope 属性表示样式只在当前组件生效 -->
<style lang="css" scoped>

</style>

(2)在 App.vue 文件中引入刚刚创建的 Learn.vue:

<template>
  <div id="app">
    <Learn />
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      message: ''
    }
  }
  
};
</script>

2、使用 props 传递数据(父传子)

通常常父组件的模板中包含子组件,父组件要正向地向子组件传递数据或参数,子组件接收到后根据参数的不同来渲染不同的内容或执行操作。这个正向传递数据的过程就是通过 props 来实现的。

在组件中,使用选项props 来声明需要从父级接收的数据, props 的值可以是两种, 一种是字符串数组,一种是对象:

1、使用字符串数组方式传递:

父组件 App.vue:

<template>
  <div id="app">
    <!-- 将 message 参数传递给子组件  -->
    <Learn message="来自父组件的数据"/>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      
    }
  }
  
};
</script>

Learn.vue 子组件:

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <p>{{ message }}</p>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {

    },
    // 接收父级组件传递的数据
    props: ['message']      
}
</script>

2、使用对象方式传递:

父组件 App.vue:

<template>
  <div id="app">
    <!-- 将 message 参数传递给子组件,传递的数据为一个对象  -->
    <Learn :message="message"/>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      // 返回一个对象
      message: {
        id: 1,
        text: '这是父组件数据'
      }
    }
  }
  
};
</script>

子组件 Learn.vue:

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <p>{{ message.text }}</p>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {

    },
    // 接收父级组件传递的数据
    props: ['message']      
}
</script>

3、自定义事件向父组件传递数据(子传父)

当子组件需要向父组件传递数据时,就要用到自定义事件。我们在介绍指令v-on 时有提到,v-on 除了监昕DOM 事件外,还可以用于组件之间的自定义事件。

子组件用 $emit() 来触发事件,父组件用 $on 来监听子组件的事件。

子组件 Learn.vue :

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <button @click="sendMsg" type="button" name="button">传递数据</button>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {

    },
    methods: {
        sendMsg() {
            // 第一个参数 getMsg 为自定义事件名,第二个为传递的值
            this.$emit("getMsg", "这是儿子的数据")
        }
    }
       
}
</script>

父组件 App.vue:

<template>
  <div id="app">
    接收的子组件数据:{{ message }}
    <!-- 监听自定义事件 getMsg -->
    <Learn @getMsg="getSonMsg"/>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      message: ''
    }
  },
  methods: {
    getSonMsg(message) {
      // message 为子组件传递的参数值
      this.message = message
    }
  }
  
};
</script>

如上,在点击传递数据按钮后,可以看到子组件给父组件传递的数据。

4、在自定义组件上使用 v-model 指令

子组件 Learn.vue:

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <input type="text" v-model="searchText">
        <button @click="sendMsg" type="button" name="button">传递数据</button>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {
        return {
            searchText: ''
        }
    },
    methods: {
        sendMsg() {
            // 第一个参数 getMsg 为自定义事件名,第二个为传递的值
            this.$emit("getMsg", this.searchText)
        }
    }
       
}
</script>

父组件 App.vue:

<template>
  <div id="app">
    接收的子组件数据:{{ message }}
    <!-- 监听自定义事件 getMsg -->
    <Learn @getMsg="getSonMsg"/>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      message: ''
    }
  },
  methods: {
    getSonMsg(message) {
      // message 为子组件传递的参数值
      this.message = message
    }
  }
  
};
</script>

如上,当在文本框输入信息后,再点击传递数据按钮,父组件成功接收到子组件传递的数据。

5、props 验证

一般当你组件需要提供给别人使用时,推荐都进行数据验证。比如某个数据必须是数字类型,如果传入字符串,就会在控制台显示警告。

父组件 App.vue:

<template>
  <div id="app">
    <Learn name="张三" age="26"/>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
     
    }
  }
};
</script>

子组件 Learn.vue:

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <p>{{ name }}</p>
        <p>{{ age }}</p>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {
        return {
        }
    },
    props: {
        // 必须是字符串类型
        name: String,
        // 自定义一个验证函数
        age: {
            validator: function(value) {
                return value > 30
            }
        }
    }
}
</script>

通过浏览器控制台发现,当父组件传递给子组件的参数验证失败时,会给出相应的警告信息。

props 常用验证示例如下:

 6、处理边界情况

(1)访问根实例:

main.js:

import Vue from 'vue'
import App from './App'

Vue.config.productionTip = false


/* eslint-disable no-new */
new Vue({
  el: '#app',
  render: h => h(App),
  // 设置根实例数据
  data: function() {
    return {
      name: 'rootData'
    }
  },
  // 设置根实例方法
  methods: {
    rootMethod: function() {
      return "rootHandler"
    }
  },
  // 设置根实例计算属性
  computed: {
    rootComputed: function() {
      return "rootComputed"
    }
  }
})

App.vue:

<template>
  <div id="app">
     <Learn/>
     <button @click="getRootData">获取根实例数据</button>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      
    }
  },
  methods: {
    getRootData() {
        // 访问根实例中的 data 数据
        console.log(this.$root.name);
        // 访问根实例中的方法
        console.log(this.$root.rootMethod)
        // 访问根实例中的计算属性
        console.log(this.$root.rootComputed)
        // 写入根实例的数据
        this.$root.age = 20;
        console.log(this.$root.age);
    }
  }
  
};
</script>

当点击按钮后,成功获取到根实例的相关信息。

对于小型应用,这样的使用方式是很方便的。不过这个模式扩展到中大型应用来说就不然了。因此在绝大多数情况下,还是推荐使用 Vuex 来处理。

(2)访问父级组件实例:

父组件 App.vue :

<template>
  <div id="app">
     <Learn/>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  // 设置父组件实例数据
  data() {
    return {
      parentName: 'parentName'
    }
  },
  // 设置父组件实例方法
  methods: {
    parentMethod: function() {
      return "parentMethod"
    }
  },
  // 设置父组件实例计算属性
  computed: {
    parentComputed: function() {
      return "parentComputed"
    }
  }
  
};
</script>

子组件 Learn.vue :

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
        <button @click="getParentInfo">获取父组件实例数据</button>
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 所有初始化数据全部放入 data 中
    data() {
        return {
           
        }
    },
    methods: {
        getParentInfo: function() {
            // 访问父组件实例的 data 数据
            console.log(this.$parent.parentName);
            // 访问父组件实例的方法
            console.log(this.$parent.parentMethod);
            // 访问父组件实例的计算属性
            console.log(this.$parent.parentComputed);
        }
    }
    
}
</script>

当点击按钮后,成功获取到父组件实例的相关数据。

(3)访问子组件实例:

有时候仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的,可以通过 ref 特性为这个子组件赋予一个ID引用。

子组件 Learn.vue :

<template>
    <!-- 只能存在一个根容器 -->
    <div class="container">
    </div>
</template>

<script>
export default {
    name: "Learn",
    // 设置子组件 data 数据
    data() {
        return {
           childData: 'childData'
        }
    },
    
    // 设置子组件方法
    methods: {
        childMethod: function() {
            return "childMethod"
        }
    },

    // 设置子组件计算属性
    computed: {
        childComputed: function() {
            return "childComputed"
        }
    }
    
}
</script>

父组件 App.vue :

<template>
  <div id="app">
     <!-- 给子组件 Learn 赋予一个 ID引用 -->
     <Learn ref="child"/>
     <button @click="getChildInfo">获取子组件实例数据</button>
  </div>
</template>
<script>
// 导入组件
import Learn from "./components/Learn"

export default {
  name: "App",
  components: {
    Learn   // 注入
  },
  data() {
    return {
      
    }
  },
  methods: {
    getChildInfo: function() {
       // 访问子组件实例 data 数据
       console.log(this.$refs.child.childData);
       // 访问子组件实例的方法
       console.log(this.$refs.child.childMethod);
       // 访问子组件实例的计算属性
       console.log(this.$refs.child.childComputed);

    }
  }
  
};
</script>

当点击按钮后,成功获取到子组件实例的相关数据。

 

 

 

 

参考:

《Vue.js 实战》

https://cn.vuejs.org/v2/guide/

posted @ 2020-03-24 20:30  d0usr  阅读(182)  评论(0编辑  收藏  举报