vue.js component 学习手记

1 global register
2 local register
3 template parsing caveats
4 data 必须是函数
5 props down, events up
6 dynamic props
7 数值传递和字串传递
8 自定义事件
9 scope
10 dynamic component

1 global register

<div id="example">
    <my-component></my-component>
</div>
Vue.component('my-component',{
    template:'<div>A custom component!</div>'
});

new Vue({
    el:'#example'
});

ps: 需要注意的是,component会重新绘制#example元素,所以,渲染后,#example就不存在了,第一层div就是component

2 local register

使用components option

<div id="local-component">
    <h1>local component</h1>
    <my-local-component></my-local-component>
</div>
let Child = {
    template:'<div>A local component!</div>'
};

new Vue({
    el:'#local-component',
    components:{
        'my-local-component':Child
    }
});

3 template parsing caveats

invalid content

<table>
  <my-row>...</my-row>
</table>

valid content 使用 is

<table>
  <tr is="my-row"></tr>
</table>

4 data 必须是函数

let data = {
    message:'hello'
};

let Child = {
    template:'<div>{{message}}</div>',
    data:function () {
        return {message:'hello'};
    }
};

new Vue({
    el:'#local-component',
    components:{
        'my-local-component':Child
    }
});

5 props down, events up

ps:父属性的变化会引起子component属性的变化,反正不然

191829_icny_2510955.png

<div id="props-example">
    <child message="hello"></child>
</div>
let child = {
    template:'<span>{{message}}</span>',
    props:['message']
}
new Vue({
    el:'#props-example',
    components:{
        'child':child
    }
});

这里有两种情况需要子component 去改变prop

  • 这个prop只是传递过来一个初始值,子component会使用它创建一个新的属性
  • prop是粗糙的原始值,需要经过处理子component才可以使用

上述两个case对应的方法:

  • 子component定义一个local data property,使用父传递的prop作为初始值
  • 子component定义一个computed property, 使用父传递的prop计算

当prop是Array 或 Object时,传递的就是reference, 所以子component对prop的操作,会影响到父的数据

6 dynamic props

不使用component

<div id="dynamic-props">
    <input v-model="parentMsg" />
    <span>{{parentMsg}}</span>
</div>
new Vue({
    el:'#dynamic-props',
    data:{
        parentMsg:'pengqin'
    }
});

使用component

<div id="dynamic-props">
    <input v-model="parentMsg" />
    <dynamic-child v-bind:message="parentMsg"></dynamic-child>
</div>
let dynamicChild = {
    template:'<span>{{message}}</span>',
    props:['message']
};

new Vue({
    el:'#dynamic-props',
    data:{
        parentMsg:'hello'
    },
    components:{
        'dynamic-child':dynamicChild
    }
});

7 数值传递和字串传递

<!-- this passes down a plain string "1" -->
<comp some-prop="1"></comp>

使用v-bind,传递数值属性值为number

<!-- this passes down an actual number -->
<comp v-bind:some-prop="1"></comp>

7 prop validation 属性验证

属性值的类型可以限制,加以验证

下面的例子就要求component的message属性值必须是Number类型

<div id="validation">
    <validation-component v-bind:message="propA"></validation-component>
</div>
let validationComponent = {
    template:'<div class="validation-component">{{message}}</div>',
    props:{
        message:Number
    }
};

new Vue({
    el:'#validation',
    data:{
        propA:123
    },
    components:{
        'validation-component':validationComponent
    }
});

下面是多种validation的组合,有默认值设置default, 必须项required,还有自定义的validator function

Vue.component('example', {
  props: {
    // basic type check (`null` means accept any type)
    propA: Number,
    // multiple possible types
    propB: [String, Number],
    // a required string
    propC: {
      type: String,
      required: true
    },
    // a number with default value
    propD: {
      type: Number,
      default: 100
    },
    // object/array defaults should be returned from a
    // factory function
    propE: {
      type: Object,
      default: function () {
        return { message: 'hello' }
      }
    },
    // custom validator function
    propF: {
      validator: function (value) {
        return value > 10
      }
    }
  }
})

type可以为6类:Number, String, Boolean, Function, Array, Object

如果是自定义的构造函数,使用instanceof

8 自定义事件

 8.1 同样使用v-on绑定自定义事件的handler

<div id="counter-event-example">
    <p>{{total}}</p>
    <button-counter v-on:increment="incrementTotal"></button-counter>
    <button-counter v-on:increment="incrementTotal"></button-counter>
</div>
Vue.component('button-counter',{
    template:'<button v-on:click="clickedButton">{{counter}}</button>',
    data:function () {
        return {
            counter: 0
        }
    },
    methods:{
        clickedButton:function () {
            this.counter += 1;
            this.$emit('increment');
        }
    }
});

new Vue({
    el:'#counter-event-example',
    data:{
        total:0
    },
    methods:{
        incrementTotal:function () {
            this.total += 1;
        }
    }
});

通过自定义事件,将父方法传递给子,子在事件方法里面可以调用父传递过来的方法,从而修改父的数值,是在子中修改父数据的一种方法

 8.2 form input comoponents 使用 自定义事件

通过input的事件绑定,看一下v-model的原理

<input v-model="something">

其实,拆分成事件,就是如下的样子

<input v-bind:value="something" v-on:input="something = $event.target.value">

可以看出,使用了value props, 触发了input 事件

总结就是,要模仿v-model,需要满足下面两个条件

  • accept a value prop
  • emit an input event with the new value
<div id="v-model-example">
    <p>{{ message }}</p>
    <my-input label="Message" v-model="message"></my-input>
</div>
Vue.component('my-input',{
    template:`<div class="form-group">
                <label v-bind:for="randomId">{{ label }}:</label>
                <input v-bind:id="randomId" v-bind:value="value" v-on:input="onInput" />
            </div>`,
    props:['label','value'],
    data:function () {
        return {
            randomId:'input-' + Math.random()
        };
    },
    methods:{
        onInput:function (event) {
            this.$emit('input',event.target.value);
        }
    }
});
new Vue({
    el: '#v-model-example',
    data: {
        message: 'hello'
    }
});

9 scope

金句:

Everything in the parent template is compiled in parent scope;

everything in the child template is compiled in child scope.

下面的例子中,message是父数据

work!

<child-component>
  {{ message }}
</child-component>

下面的例子v-show应该绑定父数据

not work!

<child-component v-show="someChildProperty"></child-component>

绑定子数据,需要在子模板中

Vue.component('child-component', {
  // this does work, because we are in the right scope
  template: '<div v-show="someChildProperty">Child</div>',
  data: function () {
    return {
      someChildProperty: true
    }
  }
})

9.1 slot 可以用来放fallback

my-component

<div>
  <h1>I'm the parent title</h1>
  <my-component>
    <p>This is some original content</p>
    <p>This is some more original content</p>
  </my-component>
</div>

a parent that use my-component

<div>
  <h2>I'm the child title</h2>
  <slot>
    This will only be displayed if there is no content
    to be distributed.
  </slot>
</div>

rendered

<div>
  <h1>I'm the parent title</h1>
  <div>
    <h2>I'm the child title</h2>
    <p>This is some original content</p>
    <p>This is some more original content</p>
  </div>
</div>

9.2 named slot可以组合app layout

app-layout template

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

parent use

<app-layout>
  <h1 slot="header">Here might be a page title</h1>
  <p>A paragraph for the main content.</p>
  <p>And another one.</p>
  <p slot="footer">Here's some contact info</p>
</app-layout>

rendered

<div class="container">
  <header>
    <h1>Here might be a page title</h1>
  </header>
  <main>
    <p>A paragraph for the main content.</p>
    <p>And another one.</p>
  </main>
  <footer>
    <p>Here's some contact info</p>
  </footer>
</div>

10 dynamic component

炫酷的动态组件切换,利用保留的<component>和绑定is属性(v-bind:is='someComponentName')

keep-alive 可以记录组件的状态,避免重新渲染

<div id="dynamic-component">
    <keep-alive>
        <component v-bind:is="currentView"></component>
    </keep-alive>
</div>
let Home = {
    template:'<p>home</p>'
};

let Posts = {
    template:'<p>posts</p>'
};

new Vue({

    el:'#dynamic-component',
    data:{
        currentView:'posts'
    },

    components:{
        home:Home,
        posts:Posts
    }
});

11 child component refs

<div id="parent">
  <user-profile ref="profile"></user-profile>
</div>
var parent = new Vue({ el: '#parent' })
// access child component instance
var child = parent.$refs.profile

ps: $ref 只有当component render后才会计算,并且不会react,所以避免在template 和 computed中使用

转载于:https://my.oschina.net/u/2510955/blog/755535

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值