Vue-components

vue component组件 - 幕布
  • vue component组件
    • 全局化注册组件 (全局组件) Vue.component
      全局组件可在多个构造器的作用域中使用;
      例子:​

      <h1>component-1</h1>
          <hr>
          <div id="app">
              <jspang></jspang>
          </div>
          <script type="text/javascript">
              //注册全局组件
              Vue.component('jspang',{
                  template:`<div style="color:red;">全局化注册的jspang标签</div>`
              })
              var app=new Vue({
                  el:'#app',
                  data:{
                  }
              })
          </script>
    • 局部注册组件(局部组件)
      局部注册的组件只能在组件注册的作用域里进行使用,其他作用域使用无效。

      例子:
      ​​​<body>
          <h1>component-1</h1>
          <hr>
          <div id="app">
            <panda></panda>
          </div>
          <script type="text/javascript">
              var app=new Vue({
                  el:'#app',
                  components:{
                      "panda":{
                          template:`<div style="color:red;">局部注册的panda标签</div>`
                      }
                  }
              })
          </script>
      </body>

      注意:​构造器里的components 是加s的,而全局注册是不加s的。还有components对象中的组件名称需要加‘’,需为字符串,不然后报错称未定义;
    • 组件和指令的区别
      组件注册的是一个标签,而指令注册的是已有标签里的一个属性。在实际开发中我们还是用组件比较多,指令用的比较少。因为指令看起来封装的没那么好,这只是个人观点。
    • component组件props属性设置
      • 定义属性并获取属性值
        定义属性我们需要用props选项,加上数组形式的属性名称,例如:props:[‘here’]。在组件的模板里读出属性值只需要用插值的形式,例如{{ here }}.

        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <script type="text/javascript" src="../assets/js/vue.js"></script>
            <title>component-2</title>
        </head>
        <body>
            <h1>component-2</h1>
            <hr>
            <div id="app">
              <panda here="China"></panda>
            </div>
         
            <script type="text/javascript">
                var app=new Vue({
                    el:'#app',
                    components:{
                        "panda":{
                            template:`<div style="color:red;">Panda from {{ here }}.</div>`,
                            props:['here']
                        }
                    }
                })
            </script>
        </body>
        </html>

        上面的代码定义了panda的组件,并用props设置了here的属性值,在here属性值里传递了China给组件。
        最后输出的结果是红色字体的Panda from China.
      • 属性中带有 ' - ' 的处理方式
        我们在写属性时经常会加入’-‘来进行分词,比如:<panda   from-here=”China”></panda>,那这时我们在props里如果写成props:[‘form-here’]是错误的,我们必须用小驼峰式写法props:[‘formHere’]。
        html文件:
        <panda from-here="China"></panda>

        <panda from-here="China"></panda>
        javascript文件:
                var app=new Vue({
                    el:'#app',
                    components:{
                        "panda":{
                            template:`<div style="color:red;">Panda from {{ fromHere }}.</div>`,
                            props:['fromHere']
                        }
                    }
                })
        PS:因为这里有坑,所以还是少用-为好。
      • 在构造器里向组件中传值
        把构造器中data的值传递给组件,我们只要进行绑定就可以了。就是我们第一季学的v-bind:xxx.

        我们直接看代码:

        Html文件:
        <panda v-bind:here="message"></panda>

        javascript文件:
        var app=new Vue({
                    el:'#app',
                    data:{
                       message:'SiChuan' 
                    },
                    components:{
                        "panda":{
                            template:`<div style="color:red;">Panda from {{ here }}.</div>`,
                            props:['here']
                        }
                    }
                })

      • component父子组件关系
        • 构造器外部写局部注册组件
    • component组件中的data书写方式
      component中的data 不能像实例中直接使用 data:{},这样选项的方式进行设置,
      因为作为一个组件肯定会被多个地方复用,如果使用​ data:{}设置的话,一个组件修改了data的值,其他的组件也会跟着改变,因为他们引用的是同一个data;
      所以 需要使用 data() {return { }} 的方式, 因该是闭包的应用,这个不太懂,标记下
    • 动态组件,根据传的值不同加载不同的组件内容
      通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,我们让多个组件可以使用同一个挂载点,并动态切换:
      var vm = new Vue({
      el: '#example',
      data: {
      currentView: 'home'
      },
      components: {
      home: { /* ... */ },
      posts: { /* ... */ },
      archive: { /* ... */ }
      }
      })
      <component v-bind:is="currentView">
      <!-- 组件在 vm.currentview 变化时改变! -->
      </component>
      也可以直接绑定到组件对象上:
      var Home = {
      template: '<p>Welcome home!</p>'
      }
      var vm = new Vue({
      el: '#example',
      data: {
      currentView: Home
      }
      })
    • 组件间传值
      • 父子组件间通信
        • 父组件 → 子组件 props
          父组件向子组件传值主要是通过 props

          https://cn.vuejs.org/v2/api/#props

          props 可以是数组或对象,用于接收来自父组件的数据。props 可以是简单的数组,或者使用对象作为替代,对象允许配置高级选项,如类型检测、自定义校验和设置默认值。​​
          // 简单语法
          Vue.component('props-demo-simple', {
          props: ['size', 'myMessage']
          })

          // 对象语法,提供校验​
          Vue.component('props-demo-advanced', {
          props: {
          // 只检测类型
          height: Number,
          // 检测类型 + 其他验证
          age: {
          type: Number,
          default: 0,
          required: true,
          validator: function (value) {
          return value >= 0
          }
          }
          }
          })
          ​​
          ​​
        • 子组件 → 父组件 event
          子组件向父组件传递数据时,就只能用$emit $on相结合的方式,
          由子组件触发自定义事件,由父组件监听改事件,并接受数据;
          注意:这里有个坑,就是你绑定自定义事件的位置必须在该子组件上,比如下面的​
          <hello @newNodeEvent="parentLisen" />,绑定在了hello子组件上,如果把​@newNodeEvent="parentLisen" 放到外层,或者其他不在子组件上的位置,则无法监听到子组件的$emit


          ps:App.vue 父组件
            Hello.vue 子组件

          <!--App.vue :-->
          <template>
            <div id="app">
              <hello @newNodeEvent="parentLisen" />
            </div>
          </template>
          <script>
          import hello from './components/Hello'
          export default {
          name: 'app',
          'components': {
          hello
          },
          methods: {
          parentLisen(evtValue) {
          //evtValue 是子组件传过来的值
          alert(evtValue)
          }
          }
          }
          </script>
          ​​
          <!--Hello.vue :-->
          <template>
            <div class="hello">
              <input type="button" name="" id="" @click="chilCall()" value="子调父" />
            </div>
          </template>
          <script>
          export default {
          name: 'hello',
          'methods': {
          chilCall(pars) {
          this.$emit('newNodeEvent', '我是子元素传过来的')
          }
          }
          }
          </script>​​​
      • 非父子组件间通信
        有时候两个组件也需要通信 (非父子关系)。在简单的场景下,可以使用一个空的 Vue 实例作为中央事件总线:

        var bus = new Vue()

        // 触发组件 A 中的事件
        bus.$emit('id-selected', 1)

        // 在组件 B 创建的钩子中监听事件
        bus.$on('id-selected', function (id) {
        // ...
        });

        在复杂的情况下,我们应该考虑使用专门的状态管理模式 vuex.

        注意:如果使用了vue-cli创建的项目,就需要在外面创建一个新的vue实例,然后分别在两个组件中引用这个,才能实现同一vue实例的​​中央事件总线;​​
        比如: 新建一个eventBus.vue 里面的内容为新建一个vue实例,供其他组件引入
        ```
        import Vue from 'vue'
        export default new Vue();
        ```

        之后就可以在 componentA 和componentB中import进来:
        ```
        componentA:​
        import bus from 'eventBus.vue'​
        bus.$emit('myevent', '这是传递的数据');
        ```
        ```
        componentB:
        import bus from 'eventBus.ves'
        mounted()​ {
        let _this = this;
        bus.$on('myevent', function(msg) {
        _this.msg = msg; //注意 这里的this已经不是指向含有data的实例的,而是bus新实例化出的中央事件总线,所以在上面需要使用 let _this = this;来转换
        ​​})​
        //也可以使用 bind(this)​来须将 this 绑定在组件实例上。如果不使用 bind , 也可以使用箭头函数。​​代码如下:
        ​bus.$on('myevent', function(msg) {
                    this.msg = msg;
                .bind(this))
        ​​}​​​​​​​
        ​​
        ​​​​​
    • slot 分发 (插槽)
      用于父级组件内容向子组件中特定位置插入父级已有的HTML代码
      ```
      //父级组件:
      <template>
          <div>
              <ul>
                  <my-li :title="list[0]" v-on:remove="list.splice(index, 1)">
                      <p>这是修改后的slot</p>
                  </my-li>
              </ul>
          </div>
      </template>

      //子组件
      <template>
          <li>
              {{title}}
              <div>
                  <slot>默认slot</slot>
              </div>
          </li>
      </template>
      ​​​```
      <slot></slot>标签中可以写入默认值,如果父级在 <my-li></my-li​>中没有内容,则会显示默认值;

      ​​​**具名slot**
      ​<slot></slot>标签可以设置 name属性,然后通过父组件中的 slot=“”属性进行分别绑定

      ```​
      //父级组件:
      <template>
          <div>
              <ul>
                  <my-li :title="list[0]" v-on:remove="list.splice(index, 1)">
                      <p slot="header">这是header slot</p>
      <p slot="footer">这是footer slot</p>​
                  </my-li>
              </ul>
          </div>
      </template>​

      //子组件
      <template>
          <li>
              {{title}}
              <div>
      <slot name="header">默认herder slot</slot>​
                  <slot name="footer">默认footer slot</slot>
              </div>
          </li>
      </template>
      ​​​```​
      ​​​​
posted @ 2017-07-30 13:16  milo_蓝色大飞机  阅读(744)  评论(0编辑  收藏  举报