Vue-组件学习(组件间通信)

247 阅读3分钟

组件的创建

使用局部组件的打油诗:建子 挂子 用子

创建全局组件 第一个参数是组件名 第二个参数是配置

<body>
  <div id="app">
    <!-- 3.使用子组件 -->
    <App></App>
  </div>
  <script src="../vue.js"></script>
  <script>
    //App组件 html+css+js

    //只要创建全局组件 可以在任意地方使用 (template )
    Vue.component('Vheader', {
      template: `
        <div>
          我是导航组件
        </div>
      `
    })
    Vue.component('Vaside', {
      template: `
        <div>
          我是侧边栏组件
        </div>
      `
    })

    const Vcomtent = {
      data() {
        return {

        }
      },
      template: `
        <div>
          我是内容组件
        </div>
      `
    }

    //使用局部组件的打油诗:建子 挂子 用子
    //1.创建组件
    //注意:在组件中的data必须是一个函数,返回一个对象
    const App = {
      data() {
        return {
          msg: '我是App组件'
        }
      },
      components: {
        Vcomtent
      },
      template: `
        <div>
          <div>
          {{msg}}
          <button @click='handleClick'>改变<button>
          </div>
          <div>
            <Vheader></Vheader>
            <Vaside />
            <Vcomtent />
          </div>
        </div>
      `,
      methods: {
        handleClick() {
          this.msg = '我被改变了'
        }
      },
    }
    new Vue({
      el: '#app',
      data: {

      },
      components: {
        //2. 挂载子组件
        App
      }
    })
  </script>
</body>

组件通信

父传子:通过props来进行通信

  1. 在父组件的子组件中声明并绑定props接收父组件挂载的属性
  2. 在子组件中定义props里父组件传过来的属性
  3. 可以在子组件中template任意使用
<body>
  <div id="app">
    <App></App>
  </div>
  <script src="../vue.js"></script>
  <script>
  
    //全局组件(子组件)
    Vue.component('Child', {
      template: `
      <div>
        <h3>我是一个孩子组件</h3>
        <h4>{{childData}}</h4>
      <div>
      `,
      // 接收父组件传来的数据
      props:['childData']
    })

    (父组件)
    const App = {
      data() {
        return {
          msg: '我是父组件传进来的值'
        }
      },
      // 绑定子组件的属性
      template: `
        <div>
          <Child :childData = 'msg'></Child>
        </div>
      `,
    }
    
    new Vue({
      el: '#app',
      data: {
      },
      components: {
        App
      }
    })
  </script>
</body>

子传父

两种解释
1.

在父组件中 子组件上绑定自定义事件

在子组件中 触发原生的事件 在事件函数中通过this.$emit触发自定义事件

在子组件绑定事件并定义方法,在方法中用this.$emit绑定要传输给父组件的值以及自定义的名字

在父组件的子组件部分绑定要传输过来的事件的自定义名字

<body>

  <div id="app">
    <App></App>
  </div>
  
  <script src="../vue.js"></script>
  <script>
  
    //全局组件(子组件)
    Vue.component('Child', {
      template: `
      <div>
        <h3>我是一个孩子组件</h3>
        <h4>{{childData}}</h4>
        <input type="text" @input='handleInput' />
      </div>
      `,
      methods: {
        handleInput(e){
          const val = e.target.value;

          this.$emit('inputHandler',val)
        }
      },
      // 接收父组件传来的数据
      props: ['childData']
    })

    (父组件)
    const App = {
      data() {
        return {
          msg: '我是父组件传进来的值',
          newVal : ''
        }
      }, 
      methods: {
        input(newData){
          this.newVal = newData;
        }
      },
      // 绑定子组件的属性
      //@inputHandler = 'input'等于挂载
      template: `
        <div>
          <div clsaa='father'>
            数据:{{newVal}}
          </div>
          <Child :childData = 'msg' @inputHandler = 'input'></Child>
        </div>
      `,
    }
    
    new Vue({
      el: '#app',
      data: {

      },
      components: {
        App
      }
    })
  </script>
</body>

平行组件通信

需要中间一个载体来为两个不相连(相对的)的组件作为直接连接载体 如例子中的bus

<body>
  <div id="app">
    <App></App>
  </div>
  <script src="../vue.js"></script>
  <script>
  
    const bus = new Vue();
    //中央事件总线 bus
    
    Vue.component('B',{
      data(){
        return{
          count:0
        }
      },
      template:`
        <div>{{count}}</div>
      `,
      //created()在当前组件创建的时候就会被立即调用
      created() {
        //$on 绑定事件
        bus.$on('add',(n)=>{
          this.count += n;
        })
        //$emit 触发事件
      },
    })

    Vue.component('A',{
      data(){
        return{
          count:1
        }
      },
      template:`
        <div>
          <button @click='handleClick'>加入购物车</button>
        </div>
      `,
      methods: {
        handleClick(){
          //触发绑定的函数
          bus.$emit('add',1);
        }
      },
    })

    const App = {
      // 绑定子组件的属性
      template: `
        <div>
          <A></A>
          <B></B>
        </div>
      `,
    }
    new Vue({
      el: '#app',
      data: {
      },
      components: {
        App
      }
    })
  </script>
</body>

组件的其他通信方式

1. provide,inject:

父组件 provide来提供变量,然后在子组件中通过inject来注入变量,无论组件嵌套多深都可以用

2. praent、children

$.parent 以及$.children获取父子组件
(created里面访问不到$.children[0、1、2这些数字])是因为这时候子组件还没被创建出来
<body>
  <div id="app">
    <App></App>
  </div>
  <script src="../vue.js"></script>
  <script>
    const bus = new Vue();

    //中央事件总线 bus
    Vue.component('B', {
      data() {
        return {
          count: 0
        }
      },
      //子组件用inject获取父组件provide的变量
      inject:['msg'],
      //在模板字符串直接使用
      template: `
        <div>
          {{msg}}
        </div>
      `,
      //created中使用要加this
      created(){
        console.log(this.msg);
      }
    })

    Vue.component('A', {
      data() {
        return {
          count: 1
        }
      },
      //$.parent以及$.children
      created(){
        console.log(this.$parent.title);
        console.log(this.$parent.$parent);
        console.log(this.$children);
      },
      template: `
        <div>
          <B></B>
        </div>
      `
    })

    const App = {
      data() {
        return {
          title:'父组件的标题'
        }
      },
      provide(){
        return{
          msg:'父组件的数据'
        }
      },
      template: `
        <div>
          <A></A>
        </div>
      `
    }
    new Vue({
      el: '#app',
      data: {
      },
      components: {
        App
      }
    })
  </script>
</body>

异步加载组件

挂载模块组件

在要挂载模块组件的组件里的compenents中

components:{
Test(自己取名):()=>import('模块路径')
}

在模块中正常用export即可 可以把要抛出的组件写成一个对象

ps:引用模块化 要记得在当前的script脚本里加入 type='module'