博客列表 >Vue2 组件

Vue2 组件

Lon
Lon原创
2021年11月03日 20:04:01960浏览

Vue2 组件

了解更多详情请访问 https://cn.vuejs.org/v2/guide/index.html

视频教程 https://www.bilibili.com/video/BV1Zy4y1K7SH

一、组件

组件是一种封装可复用的集合,通过组件化,将更好的完成繁杂的需求

组件化特点,具体如下:
1.拥有唯一性的组件名称,方便调用;
2.以组件名称为 HTML 元素标签形式存在,扩展了 HTML;
3.组件可以复用,且组件与组件之间互不干涉;

Vue中使用组件的三大步骤:
1.定义组件(创建组件)
2.注册组件(分为全局注册和局部注册)
3.使用组件(写组件标签)

二、注册组件

局部注册:在实例选项中注册局部组件,这样组件只能在这个实例中使用
全局注册:所有实例都能用全局组件

  1. <div id="root">
  2. <!-- 第三步:编写组件标签 -->
  3. <hello></hello>
  4. <hr>
  5. <h1>{{msg}}</h1>
  6. <hr>
  7. <!-- 第三步:编写组件标签 -->
  8. <student ></student>
  9. </div>
  10. </body>
  11. <script>
  12. Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
  13. //第一步:创建student组件
  14. const student = Vue.extend({
  15. template:`
  16. <div>
  17. <h2>学生姓名:{{studentName}}</h2>
  18. <h2>学生年龄:{{age}}</h2>
  19. </div>
  20. `,
  21. data(){
  22. return{
  23. studentName:'张三',
  24. age:18
  25. }
  26. }
  27. })
  28. //第一步:创建hello组件
  29. const hello = Vue.extend({
  30. template:`
  31. <div>
  32. <h2>你好啊!{{name}}</h2>
  33. </div>
  34. `,
  35. data(){
  36. return{
  37. name:'Tom'
  38. }
  39. }
  40. })
  41. //第二步:全局注册组件
  42. Vue.component('hello',hello)
  43. //创建vm
  44. new Vue({
  45. el:'#root',
  46. data:{
  47. msg:'你好啊!'
  48. },
  49. //第二步,注册组件(局部组件)
  50. components:{
  51. student
  52. }
  53. })
  54. </script>

注意:

1.Vue.extend()是一个基础构造器(全局 API),意图创建一个子类;

2.Vue.component()是注册组件,参数 1 为名称,参数 2 为extend()

3.data必须写成函数,避免组件被复用时,数据存在引用关系。

三、组件的嵌套

组件和组件之间可以嵌套,形成一种父子关系的组件

  1. <div id="root">
  2. </div>
  3. </body>
  4. <script>
  5. Vue.config.productionTip = false
  6. //定义student组件
  7. const student = Vue.extend({
  8. name:'student',
  9. template:`
  10. <div>
  11. <h2>学生姓名:{{name}}</h2>
  12. <h2>学生年龄:{{age}}</h2>
  13. </div>
  14. `,
  15. data(){
  16. return {
  17. name:'张三',
  18. age:18
  19. }
  20. }
  21. })
  22. //定义school组件
  23. const school = Vue.extend({
  24. name:'school',
  25. //嵌套student组件
  26. template:`
  27. <div>
  28. <h2>学生名称:{{name}}</h2>
  29. <h2>学生地址:{{address}}</h2>
  30. <student></student>
  31. </div>
  32. `,
  33. data(){
  34. return{
  35. name:'张三',
  36. address:'北京'
  37. }
  38. },
  39. //注册组件(局部)
  40. components:{
  41. student
  42. }
  43. })
  44. //定义hello组件
  45. const hello = Vue.extend({
  46. template:`<h1>{{msg}}</h1>`,
  47. data(){
  48. return{
  49. msg:'holle vue'
  50. }
  51. }
  52. })
  53. //定义app组件
  54. const app = Vue.extend({
  55. //嵌套school、hello组件
  56. template:`
  57. <div>
  58. <hello></hello>
  59. <school></school>
  60. </div>
  61. `,
  62. //注册组件(局部)
  63. components:{
  64. school,
  65. hello
  66. }
  67. })
  68. new Vue({
  69. template:'<app></app>',
  70. el:"#root",
  71. //注册组件(局部)
  72. components:{app}
  73. })
  74. </script>

四、组件的 props 通信

1.组件的 props

1.组件的父子关系中,当设置一个独立组件时,这个组件就是 new Vue()的子组件;

2.当我们需要通过子组件显示父组件 data 值的时候,需要通过 props 属性传值

  1. <div id="root">
  2. <student text="李四"></student>
  3. //也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
  4. <student v-bind:text="message"></student>
  5. </div>
  6. <script>
  7. //去掉警告
  8. Vue.config.productionTip = false;
  9. //局部组件
  10. const childComponent = Vue.extend({
  11. data() {
  12. // 子组件和父组件都有 message 属性,同时调用并不冲突;顺序也可控;
  13. return {
  14. message : '局部组件'
  15. }
  16. },
  17. //使用传过来的text
  18. template : `
  19. <div>{{text}} {{message}}</div>
  20. `,
  21. // 声明 props
  22. props : ['text']
  23. });
  24. //数据对象
  25. const dataObj = {
  26. message : '张三三',
  27. };
  28. //创建一个Vue对象
  29. //父组件
  30. const root = new Vue({
  31. el : '#root',
  32. data:dataObj,
  33. // data(){
  34. // return{
  35. // message: '张三三',
  36. // }
  37. // },
  38. components : {
  39. 'student' : childComponent
  40. },
  41. });
  42. </script>

2.组件的 props 单向数据流

1.父组件的 data 值更新后通过 props 选项交给子组件进行渲染,反之则不行;

2.这就是单向数据流(单向下行绑定),不能通过子组件来改变父组件的状态;

3.这样做的是为了防止父组件发生改变后,数据流变得难以理解;

4.父组件更新时,子组件所有 props 值也会更新,你不能改变子组件的 props 值

  1. <div id="root">
  2. <html-a v-bind:count="count"></html-a>
  3. </div>
  4. <script>
  5. //去掉警告
  6. Vue.config.productionTip = false;
  7. //局部组件
  8. const childComponent = Vue.extend({
  9. data() {
  10. return {
  11. message : '子组件',
  12. }
  13. },
  14. template : `
  15. <button v-on:click="count++">{{count}}</button>
  16. `,
  17. props : ['count'],
  18. })
  19. //创建一个Vue对象
  20. //父组件
  21. const root = new Vue({
  22. el : '#root',
  23. data : {
  24. count : 5
  25. },
  26. components : {
  27. 'html-a' : childComponent
  28. },
  29. });
  30. </script>

注意:

​ 以上内容,会正确改变了 props 的值,也渲染到视图中,但控制台报错;

​ 意为:不可以直接修改 props 值,可以通过数据或计算属性来解决;

  1. <div id="root">
  2. <html-a v-bind:count="count"></html-a>
  3. </div>
  4. <script>
  5. //去掉警告
  6. Vue.config.productionTip = false;
  7. //局部组件
  8. const childComponent = Vue.extend({
  9. //通过使用 data 数据更改
  10. data() {
  11. return {
  12. message : '子组件',
  13. childCount : this.count
  14. }
  15. },
  16. template : `
  17. <button v-on:click="clickChildCount">{{changedChildCount}}</button>
  18. `,
  19. props : ['count'],
  20. //通过使用计算属性和方法数据更改
  21. computed: {
  22. changedChildCount() {
  23. return this.childCount;
  24. }
  25. },
  26. methods: {
  27. clickChildCount() {
  28. this.childCount++
  29. }
  30. }
  31. })
  32. //创建一个Vue对象
  33. //父组件
  34. const root = new Vue({
  35. el : '#root',
  36. data : {
  37. count : 5
  38. },
  39. components : {
  40. 'html-a' : childComponent
  41. },
  42. });
  43. </script>

3.组件的 props 验证

1.之前props 选项通信采用的是数组方式,其实还有第二种方式:对象;

2.通过对象模式进行传递数据,可以对数据类型进行验证,支持的类似有:

Sting.Number.Boolean.Function.Object.Array.Symbo

  1. <div id="root">
  2. <student name="李四" sex="女" :age="18"></student>
  3. </div>
  4. <script>
  5. //去掉警告
  6. Vue.config.productionTip = false;
  7. //局部组件
  8. const childComponent = Vue.extend({
  9. //通过使用 data 数据更改
  10. data(){
  11. console.log(this)
  12. return{
  13. msg:'我是一个学生',
  14. myAge:this.age
  15. }
  16. },
  17. template : `
  18. <div>
  19. <h1>{{msg}}</h1>
  20. <h2>学生姓名:{{name}}</h2>
  21. <h2>学生性别:{{sex}}</h2>
  22. <h2>学生年龄:{{myAge+1}}</h2>
  23. <button @click="updateAge">尝试修改收到的年龄</button>
  24. </div>
  25. `,
  26. methods: {
  27. updateAge(){
  28. this.myAge++
  29. }
  30. },
  31. //简单声明介绍
  32. // props:['name','age','sex']
  33. //接收的同时对数据进行类型限制
  34. // props:{
  35. // name:String,
  36. // age:Number,
  37. // sex:String
  38. // }
  39. //接收的同时对数据进行类型限制
  40. props:{
  41. name:{
  42. type:String,//name的类型是字符串
  43. required:true,//name是必须要的
  44. },
  45. age:{
  46. type:Number,
  47. default:18//默认值
  48. },
  49. sex:{
  50. type:String,
  51. required:true
  52. }
  53. }
  54. })
  55. //父组件
  56. const root = new Vue({
  57. el : '#root',
  58. data : {
  59. count : 5
  60. },
  61. components : {
  62. 'student' : childComponent
  63. },
  64. });
  65. </script>

五、组件的自定义事件

父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!

我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:

  • 使用 $on(eventName) 监听事件
  • 使用 $emit(eventName) 触发事件

另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。

  1. <div id="root">
  2. {{message}}
  3. <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on)-->
  4. <html-a v-on:child="parentFn"></html-a>
  5. </div>
  6. <script src="../js/vue.js"></script>
  7. <script>
  8. //去掉警告
  9. Vue.config.productionTip = false;
  10. //子组件
  11. const childComponent = Vue.extend({
  12. data() {
  13. return {
  14. name : 'Mr.Lon'
  15. }
  16. },
  17. template : `
  18. <div>
  19. <button v-on:click="childClick">点我把名字传给父组件</button>
  20. </div>
  21. `,
  22. methods : {
  23. childClick() {
  24. //触发子组件实例身上的child事件
  25. this.$emit('child', this.name)
  26. }
  27. }
  28. })
  29. //父组件
  30. const root = new Vue({
  31. el : '#root',
  32. data : {
  33. message : 'Hello, Vue!'
  34. },
  35. components : {
  36. 'html-a' : childComponent
  37. },
  38. //方法
  39. methods : {
  40. parentFn(name) {
  41. this.message = name;
  42. console.log('子组件传递给父组件!' + name);
  43. }
  44. }
  45. });
  46. </script>
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议