详细讲解vuecli中的vue组件化与父子通信

1 简介

  • vuecli 中提供一种简单的方式进行组件化开发。
  • 注意
    • 引入 js 模块和引入 vue 模块是不一样的。引入 js 模块是全局引入,而引入 vue 模块是局部引入。在不同模块下引入相同的 js 模块,当修改js模块中的变量时,会在全局影响,所有引入该模块的文件都能察觉该改动。但是修改 vue 模块中的变量,是不会影响全局的。

2 定义组件

  • 组件可以使用ES6模块化规范的写法,通过 import 引入其他vue或者js模块。
  • data 部分必须是方法而不是json对象!
<template>
  <div>
    {{msg}}
  </div>
</template>

<script>
export default {
  // 其他组件
  components: {},
  // 生命周期
  created() {},
  mounted() {},
  // vue 变量
  data() {
    return {
      msg: 'hello world',
    }
  },
  // 方法
  methods: {},
  // 来自父组件的消息
  props: {},
}
</script>

3 父组件中使用

  • 注意,子组件的名称与引入时起的名称有关与文件名无关。引入的时候必须采取驼峰命名法。标签使用的时候必须全小写,单词之间用"-"分割
  • 需要进行以下事情
    • 定义子组件的.vue文件
    • 在父组件中通过ES6模块化规范引入
    • 在 components 中注册
    • HTML代码中使用指定的标签名
// 引入
import helloWorlds from "@/views/demo1/hello-world.vue"
export default {
  name: 'Home',
  components: {
    // 注册组件
    helloWorlds
  }
}
  • HTML代码中使用
<template>
  <div class="home">
    <hello-worlds></hello-worlds>
  </div>
</template>

4 父组件和子组件沟通

4.1 (*)父组件提供对象

  • 通过传递对象来进行沟通
  • 需要做以下事情
    • 父组件中定义要传递的对象
    • 在父组件使用子组件的标签处传递该对象
    • 子组件在props中注册父组件传来的对象
  • 关于父子通信
    • 父组件传递给子组件的变量,如果在父组件中进行了修改,可以直接影响子组件
    • 子组件无法直接修改父组件传递的变量。但是父组件可以提供修改该变量的方法。
  • 这是父组件
<template>
  <div class="home">
    <hello-worlds :msg="msgInParent" :demo="demoInParent" ></hello-worlds>
  </div>
</template>

<script>
import helloWorlds from '@/views/demo1/hello-world.vue'
export default {
  name: 'Home',
  data() {
    return {
      msgInParent: '你好',
    }
  },
  methods:{
    demoInParent(){
      console.log("Home!!!")
    }
  },
  components: {
    helloWorlds,
  },
}
</script>
  • 这是子组件
    • type 可以为String 、Number、Boolean、Array、Object、Date、Function、Symbol
    • 注意,不允许子组件修改该值,但是你可以传递给子组件修改某个值的方法。
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  // 其他组件
  components: {},
  // 生命周期
  created() {
    this.demo()
  },
  mounted() {},
  // vue 变量
  data() {
    return {
      
    }
  },
  // 方法
  methods: {},
  // 来自父组件的消息
  props: {
    msg: {
      type: String,
      default: '我是默认值,父组件没有传给我msg'
    },
    demo:{
      type: Function,
      default: function(){
        console.log("并没有传递进方法")
      }
    }
  },
}
</script>

4.2 父组件提供方法

  • 注意,由于方法也是对象,你可以直接使用4.1中的方法进行传递。建议只用4.1中的方法进行传递。
  • 这里提供另一种传递的方法,需要做一下事情
    • 在父组件中定义一个方法,在html代码中的子组件标签上注册该方法
    • 在子组件中可以直接使用该方法
  • 这是父组件
<template>
  <div class="home">
    <hello-worlds :msg="msgInParent" @demo-in-child="demoInParent"></hello-worlds>
  </div>
</template>

<script>
import helloWorlds from '@/views/demo1/hello-world.vue'
export default {
  name: 'Home',
  mounted() {},
  data() {
    return {
      msgInParent: '你好',
    }
  },
  methods: {
    // 被注册的方法
    demoInParent() {
      console.log('Home!!!')
    },
  },
  components: {
    helloWorlds,
  },
}
</script>
  • 这是子组件
    • 在子组件中直接使用this.$emit(‘在父组件中注册的名称’,参数列表)来调用传递过来的方法
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  // 其他组件
  components: {},
  // 生命周期
  created() {
    this.$emit('demo-in-child')
  },
  mounted() {},
  // vue 变量
  data() {
    return {
      
    }
  },
  // 方法
  methods: {},
  // 来自父组件的消息
  props: {
    msg: {
      type: String,
      default: '我是默认值,父组件没有传给我msg'
    },
  },
}
</script>

4.3 子组件提供对象和方法

  • 不需要子组件做额外操作,可以全权由父组件完成。
  • 注意:这里的操作会增加代码的耦合性,不建议使用这里的操作。建议使用 4.1 中的方法,让父组件提供一个对象,子组件进行修改。
  • 父组件可以直接调用子组件的方法,也可以直接修改子组件中的变量
  • 步骤
    • 需要在父组件的html代码中的子组件上绑定 ref 作为子组件的id
    • 此时子组件的对象为 this.$refs.子组件id,可通过该对象对子组件进行修改
  • 这里是父组件
<template>
  <div class="home">
    <hello-worlds ref="helloWorld"></hello-worlds>
  </div>
</template>

<script>
import helloWorlds from '@/views/demo1/hello-world.vue'
export default {
  name: 'Home',
  mounted() {
    // 调用子组件的方法console.log()
    this.$refs.helloWorld.demo()
    // 查询子组件的值
    this.$refs.helloWorld.msg = "你好"
    console.log(this.$refs.helloWorld.msg)
  },
  data() {
    return {}
  },
  methods: {},
  components: {
    helloWorlds,
  },
}
</script>
  • 这里是子组件
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  // 其他组件
  components: {},
  // 生命周期
  created() {},
  mounted() {},
  // vue 变量
  data() {
    return {
      msg: 'hahah',
    }
  },
  // 方法
  methods: {
    demo() {
      console.log('hello-world!!!')
    },
  },
}
</script>

5 证明导入js模块和导入vue模块的不同

5.1 导入vue模块

  • 实验思路:
    * 在两个不同的模块A和B中引入一个共用的vue模块,在模块A中修改这个共用vue模块的变量,如果在模块 B 中再次查询该模块变量的时候能够察觉到被修改了,则说明是全局引入,否则是局部引入
  • 新建一个模块demo.vue
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      demodata: 1,
    }
  },
  props: {
    msg: {
      default: '我是demo',
      type: String,
    },
  },
}
</script>
  • 在两个模块中引入
    • 模块一
<template>
  <div class="home">
    <hello-worlds ref="helloWorld"></hello-worlds>
    <demo ref="demo1"></demo>
  </div>
</template>

<script>
import helloWorlds from '@/views/demo1/hello-world.vue'
import demo from '@/components/demo.vue'
export default {
  name: 'Home',
  mounted() {
    console.log(this.$refs.demo1.demodata)
    setTimeout(()=>{
      this.$refs.demo1.demodata = 2000
    },1000)
    setTimeout(()=>{
       console.log(this.$refs.demo1.demodata)
    },2000)
  },
  data() {
    return {}
  },
  methods: {},
  components: {
    helloWorlds,
    demo
  },
}
</script>
  • 模块二
<template>
  <div>
    {{ msg }}
    <br>
    <demo ref="demo1" :msg="'我是demo1——来自hello-world'"></demo>
  </div>
</template>

<script>
import demo from '@/components/demo.vue'
export default {
  // 其他组件
  components: {
    demo
  },
  // 生命周期
  created() {},
  mounted() {
    console.log(this.$refs.demo1.demodata)
    setTimeout(()=>{
       console.log(this.$refs.demo1.demodata)
    },2000)
  },
  // vue 变量
  data() {
    return {
      msg: 'hahah',
    }
  },
  // 方法
  methods: {
    demo() {
      console.log('hello-world!!!')
    },
  },
}
</script>
  • 结果是
1
1
1
2000
  • 这说明是局部引入

5.2 导入js模块

  • 实验思路
    • 在两个不同的模块A和B中引入一个共用的js模块,在模块A中修改这个共用js模块的变量,如果在模块 B 中再次查询该模块变量的时候能够察觉到被修改了,则说明是全局引入,否则是局部引入
  • js模块
export default{
  msg:15
}
  • 模块一
<template>
  <div class="home">
    <hello-worlds ref="helloWorld"></hello-worlds>
  </div>
</template>

<script>
import helloWorlds from '@/views/demo1/hello-world.vue'
import demo1Api from '@/utils/demo1.js'
export default {
  name: 'Home',
  mounted() {
    console.log(demo1Api.msg)
    setTimeout(()=>{
      console.log(demo1Api.msg)
    },2000)
  },
  data() {
    return {}
  },
  methods: {},
  components: {
    helloWorlds,
  },
}
</script>
  • 模块二
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
import demo1Api from '@/utils/demo1.js'
export default {
  // 其他组件
  components: {},
  // 生命周期
  created() {},
  mounted() {
    console.log(demo1Api.msg)
    setTimeout(()=>{
      demo1Api.msg = 2000
    },1000)
    setTimeout(()=>{
      console.log(demo1Api.msg)
    },2000)
  },
  // vue 变量
  data() {
    return {
      
    }
  },
  // 方法
  methods: {},
  // 来自父组件的消息
  props: {
    msg: {
      type: String,
      default: '我是默认值,父组件没有传给我msg'
    },
  },
}
</script>
  • 结果是
15
15
2000
2000
  • 这意味着是全局导入
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值