zoukankan      html  css  js  c++  java
  • vue-8-组件

    注册

    注册一个全局组件:Vue.component(tagName, options)
    
    Vue.component('my-component', {
      template: '<div>A custom component!</div>'
    })
    <div id="example">
      <my-component></my-component>
    </div>
    
    new Vue({
      el: '#example'
    })
    
    
    局部注册:通过组件实例选项注册
    var Child = {
      template: '<div>A custom component!</div>'
    }
    new Vue({
      el: '#example'components: {//<my-component> 将只在父模板可用
        'my-component': Child
      }
    })

    使用is属性:

    <table>
      <tr is="my-row"></tr>
    //==<my-row>...</my-row>,table下标签有HTML的限制可以换用is的形式
    </table>

      使用模板,这些限制将不适用:

    1. <script type="text/x-template">

    2. JavaScript 内联模板字符串

    3. .vue 组件

    data必须是一个函数,并且,如果返回一个公共的变量,实例之间将共享数据。

    props://prop 是单向绑定的

    <child my-message="hello!"></child>
    //当使用的不是字符串模板,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名:
    Vue.component('child', { props: ['myMessage'], template: '<span>{{ myMessage }}</span>' })
    动态prop:
    <div>
      <input v-model="parentMsg">
      <child :my-message="parentMsg"></child>
    </div>
     props 传递所有的属性,绑定一个对象:
    
    todo: {
      text: 'Learn Vue',
      isComplete: false
    }
    <child v-bind="todo"></child>
    <!-- 传递实际的 number -->
    <comp v-bind:some-prop="1"></comp>
    props验证
    
    原生构造器类型:
    StringNumberBooleanFunctionObjectArraySymbol
    type 也可以是一个自定义构造器函数,使用 instanceof 检测。
    
    Vue.component('example', {
      props: {
        // 基础类型检测 (`null` 意思是任何类型都可以)
        propA: Number,
        // 多种类型
        propB: [String, Number],
        // 必传且是字符串
        propC: {
          type: String,
          required: true
        },
        // 数字,有默认值
        propD: {
          type: Number,
          default: 100
        },
        // 数组/对象的默认值应当由一个工厂函数返回
        propE: {
          type: Object,
          default: function () {
            return { message: 'hello' }
          }
        },
        // 自定义验证函数
        propF: {
          validator: function (value) {
            return value > 10
          }
        }
      }
    })

    非prop属性,也允许加入到属性,(如一些第三方组件,可以把属性直接添加到组件上 ,不需要事先定义 prop)

    <bs-date-input data-3d-date-picker="true"></bs-date-input>

    从父组件传来的属性值,如class会和组件模板定义的同名属性合并

    自定义事件

    <div id="counter-event-example">
      <p>{{ total }}</p>
      <button-counter v-on:increment="incrementTotal"></button-counter> //$on用来监听increment事件
      <button-counter v-on:increment="incrementTotal"></button-counter>
    </div>
    //子组件:
    Vue.component('button-counter', {
      template: '<button v-on:click="incrementCounter">{{ counter }}</button>',
      data: function () {
        return {
          counter: 0
        }
      },
      methods: {
        incrementCounter: function () {
          this.counter += 1
          this.$emit('increment') //$emit用来触发increment事件,调用incrementTotal方法
        }
      },
    })
    new Vue({ el: '#counter-event-example', data: { total: 0 }, methods: { incrementTotal: function () { this.total += 1 } } })

     .native 修饰符

    //在某个组件的根元素上监听一个原生事件。可以使用 .native 修饰 v-on
    <my-component v-on:click.native="doTheThing"></my-component>

    .sync 修饰符

    //双向绑定,只是作为一个编译时的语法糖
    <comp :foo.sync="bar"></comp>

    自定义的表单输入组件

    货币筛选器
    html:
    <div id="app">
      <currency-input label="Price" v-model="price"></currency-input>
      <currency-input label="Shipping" v-model="shipping"></currency-input>
      <currency-input label="Handling" v-model="handling"></currency-input>
      <currency-input label="Discount" v-model="discount"></currency-input>
      <p>Total: ${{ total }}</p>
    </div>
    
    js:
    Vue.component('currency-input', {
      template: '
        <div>
          <label v-if="label">{{ label }}</label>
          $
          <input
            ref="input"
            v-bind:value="value"
            v-on:input="updateValue($event.target.value)"
            v-on:focus="selectAll"
            v-on:blur="formatValue"
          >
        </div>
      ',
      props: {
        value: {
          type: Number,
          default: 0
        },
        label: {
          type: String,
          default: ''
        }
      },
      mounted: function () {
        this.formatValue()
      },
      methods: {
        updateValue: function (value) {
          var result = currencyValidator.parse(value, this.value)
          if (result.warning) {
            this.$refs.input.value = result.value
          }
          this.$emit('input', result.value)
        },
        formatValue: function () {
          this.$refs.input.value = currencyValidator.format(this.value)
        },
        selectAll: function (event) {
          setTimeout(function () {
              event.target.select()
          }, 0)
        }
      }
    })
    
    new Vue({
      el: '#app',
      data: {
        price: 0,
        shipping: 0,
        handling: 0,
        discount: 0
      },
      computed: {
        total: function () {
          return ((
            this.price * 100 + 
            this.shipping * 100 + 
            this.handling * 100 - 
            this.discount * 100
          ) / 100).toFixed(2)
        }
      }
    })

    自定义组件的v-model,默认一个组件的 v-model 会使用 value 属性和 input 事件,但是诸如单选框、复选框之类的输入类型把 value 属性用作了别的目的。这时需要设置组件的model选项来指定prop和event

    <my-checkbox v-model="foo" value="some value"></my-checkbox>
    Vue.component('my-checkbox', {
      model: {
        prop: 'checked',
        event: 'change'
      },
      props: {
        checked: Boolean,
        // this allows using the `value` prop for a different purpose
        value: String
      },
      // ...
    })

    编译的作用域:

    <child-component v-show="someChildProperty"></child-component>
    //someChildProperty存在于父作用域
    
    Vue.component('child-component', {
      // someChildProperty存在于子作用域
      template: '<div v-show="someChildProperty">Child</div>',
      data: function () {
        return {
          someChildProperty: true
        }
      }
    })

    内容分发:插槽

    <div>
      <h2>我是子组件的标题</h2>
      <slot>
        只有在没有要分发的内容时才会显示。
      </slot>
     <slot name="footer"></slot>
    //具名插槽 </div>
    <div>
      <h1>我是父组件的标题</h1>
      <my-component>
        <p>这是一些初始内容</p>
        <p>这是更多的初始内容</p>
    <p slot="footer">这里有一些联系信息</p>
    </my-component>
    </div>
    作用域插槽://子组件的内容可以在父组件指定
    父:
    <my-awesome-list :items="items">
      <!-- 作用域插槽也可以是具名的 -->
      <template slot="item" scope="props">
        <li class="my-fancy-item">{{ props.text }}</li>
      </template>
    </my-awesome-list>
    
    子:
    <ul>
      <slot name="item"
        v-for="item in items"
        :text="item.text">
        <!-- 这里写入备用内容 -->
      </slot>
    </ul>

    动态组件 

    var vm = new Vue({
      el: '#example',
      data: {
        currentView: 'home'
      },
      components: {
        home: { /* ... */ },
        posts: { /* ... */ },
        archive: { /* ... */ }
      }
    })
    
    <component v-bind:is="currentView">
      <!-- 组件在 vm.currentview 变化时改变! is指向的组件名随之变化-->
    </component>

    如果把切换出去的组件保留在内存中, keep-alive,可以保留它的状态或避免重新渲染

    <keep-alive>
      <component :is="currentView">
        <!-- 非活动组件将被缓存! -->
      </component>
    </keep-alive>

    子组件索引:ref 为子组件指定一个索引 ID

    <div id="parent">
      <user-profile ref="profile"></user-profile>
    </div>
    
    var parent = new Vue({ el: '#parent' })
    
    // 直接访问子组件
    var child = parent.$refs.profile

    异步组件

    全局异步组件:
    Vue.component(
      'async-webpack-example',
      () => import('./my-async-component')
    )
    
    局部异步组件:
    new Vue({
      // ...
      components: {
        'my-component': () => import('./my-async-component')
      }
    })
    
    高级异步组件://当一个异步组件被作为 vue-router 的路由组件使用时,这些高级选项都是无效的,因为在路由切换前就会提前加载所需要的异步组件
    const AsyncComp = () => ({
      // 需要加载的组件。应当是一个 Promise
      component: import('./MyComp.vue'),
      // loading 时应当渲染的组件
      loading: LoadingComp,
      // 出错时渲染的组件
      error: ErrorComp,
      // 渲染 loading 组件前的等待时间。默认:200ms。
      delay: 200,
      // 最长等待时间。超出此时间则渲染 error 组件。默认:Infinity
      timeout: 3000
    })

    组件命名约定:

    当注册组件 (或者 props) 时,可以使用 kebab-case,camelCase,或 PascalCase。

    // 在组件定义中
    components: {
      // 使用 kebab-case 形式注册
      'kebab-cased-component': { /* ... */ },
      // register using camelCase
      'camelCasedComponent': { /* ... */ },
      // register using PascalCase
      'PascalCasedComponent': { /* ... */ }
    }

    在 HTML 模板中,请使用 kebab-case 形式:

    <!-- 在 HTML 模板中始终使用 kebab-case -->
    <kebab-cased-component></kebab-cased-component>
    <camel-cased-component></camel-cased-component>
    <pascal-cased-component></pascal-cased-component>

    如果组件未经 slot 元素传递内容,你甚至可以在组件名后使用 / 使其自闭合<my-component/>

    递归组件:

    组件在它的模板内可以递归地调用自己,不过,只有当它有 name 选项时才可以

    Vue.component('stack-overflow', {
        template: '<div><stack-overflow></stack-overflow></div>'
    })
    父组件tree-folder<p>
      <span>{{ folder.name }}</span>
      <tree-folder-contents :children="folder.children"/>
    </p>
    
    子组件tree-folder-contents:
    <ul>
      <li v-for="child in children">
        <tree-folder v-if="child.children" :folder="child"/>
        <span v-else>{{ child.name }}</span>
      </li>
    </ul>
    循环引用时,需向注明模块化管理系统循环引用的组件间的处理优先级:
    
    beforeCreate: function () {
      this.$options.components.TreeFolderContents = require('./tree-folder-contents.vue').default
    }

    内联模板

    如果子组件有 inline-template 特性,组件将把它的内容当作它的模板,而不是把它当作分发内容。这让模板更灵活,不推荐。
    
    <my-component inline-template>
      <div>
        <p>These are compiled as the component's own template.</p>
        <p>Not parent's transclusion content.</p>
      </div>
    </my-component>

    模板x-template:

    //x-template:
    <script type="text/x-template" id="hello-world-template">
      <p>Hello hello hello</p>
    </script>
    Vue.component('hello-world', {
      template: '#hello-world-template'
    })

    v-once,缓存模板

    Vue.component('terms-of-service', {
      template: '
        <div v-once>
          <h1>Terms of Service</h1>
          ... a lot of static content ...
        </div>
      '
    })

     

  • 相关阅读:
    swift 第十四课 可视化view: @IBDesignable 、@IBInspectable
    swift 第十三课 GCD 的介绍和使用
    swift 第十二课 as 的使用方法
    swift 第十一课 结构体定义model类
    swift 第十课 cocopod 网络请求 Alamofire
    swift 第九课 用tableview 做一个下拉菜单Menu
    swift 第八课 CollectView的 添加 footerView 、headerView
    swift 第七课 xib 约束的优先级
    swift 第六课 scrollview xib 的使用
    swift 第五课 定义model类 和 导航栏隐藏返回标题
  • 原文地址:https://www.cnblogs.com/avidya/p/7612434.html
Copyright © 2011-2022 走看看