• 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>
      '
    })

     

  • 相关阅读:
    最优贸易 NOIP 2009 提高组 第三题
    Think twice, code once.
    luogu P1378 油滴扩展
    codevs 1002 搭桥
    codevs 1014 装箱问题 2001年NOIP全国联赛普及组
    洛谷P2782 友好城市
    洛谷P1113 杂务
    [HDU1848]Fibonacci again and again
    [POJ2420]A Star not a Tree?
    [SCOI2010]生成字符串
  • 原文地址:https://www.cnblogs.com/avidya/p/7612434.html
Copyright © 2020-2023  润新知