---
# System prepended metadata

title: Vue Component
tags: [vue, JSX]

---

# Vue Component

在父元件中使用時
```htmlembedded=
<div id="vueapp">
    <my-text1 mytitle="Title">
        <span>Note: something</span>
    </my-text1>
    <my-text1 mytitle="">
        <span style="color:red">Note: this is Note</span>
    </my-text1>
    <my-text2></my-text2>
    <my-text2 mytitle="title2">
        <span style="color:red">Note: this is Note2</span>
    </my-text2>
</div>
<script>
    window.vmApp = new Vue({
        el: '#vueapp',
        data: {
        },
        mounted: function () {},
        methods: {}
        })
</script>

```

## 膜板型Component (Template Component)
基於父元件對應的VueComponent
```htmlmixed=
<script id="my-text-template" type="text/x-template">
    <div>
        <label v-show="mytitle.length > 0"> {{ mytitle }} </label>
        <input type="text" v-model="myValue" debounce="600" />
        <slot></slot>
    </div>
</script> 
<script>
    Vue.component('myText1', {
        template: '#my-text-template',
        props: {
            mytitle: {
                type: String,
                default: 'Label Title'
            }
        },
        data: function () {
            return {
                myValue: 'smoetext'
            };
        },
        mounted: function () {
            let vm = this;
        },
        watch: {
            myValue: function (val, oldVal) {
                console.log(val, oldVal);
                if (val === oldVal) return;
                let vm = this;
                let result = '';
                if (val.length > 1) {
                    result = val.substring(0,1).toUpperCase()
                    result += val.substring(1).toLowerCase()
                    vm.myValue = result;
                }
            }
        }
    });
</script> 
```

## 渲染型Component (透過render函數產生如上x-template內容)

可對照參考 [Vue:渲染函数 & JSX](https://cn.vuejs.org/v2/guide/render-function.html#%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BB%84%E4%BB%B6)

```javascript=
    Vue.component('myText2', {  
        render: function (h) {
            let vm = this;
            let doms = [];

            if (vm.mytitle.length > 0) {
                doms.push(h('label', vm.mytitle))
            } 
            doms.push(h('input',
                {
                    attrs: {
                        type: "text",
                        debounce: "600"
                    },
                    domProps: {
                        value: vm.myValue,
                        mytitle: vm.mytitle
                    },
                    on: {
                        input: function (event) {
                            vm.myValue = event.target.value
                        }
                    }
                }));

            doms.push(vm.$slots.default)

            return h('div', doms)
        },
        props: {
            mytitle: {
                type: String,
                default: 'Label Title'
            }
        },
        data: function () {
            return {
                myValue: 'text2'
            };
        },
        mounted: function () {
            let vm = this;
        },
        watch: {
            myValue: function (val, oldVal) {
                console.log(val, oldVal);
                if (val === oldVal) return;
                let vm = this;
                let result = '';
                if (val.length > 1) {
                    result = val.substring(0, 1).toUpperCase()
                    result += val.substring(1).toLowerCase()
                    vm.myValue = result;
                }
            }
        }
    });
```

兩種寫法 my-text1 等同於 my-text2

雖然只是一次轉譯 但真的不容易...

# 注意事項

1.component 只會有一個Html根節點
2.props 用來初始資料
3.data 用來呈現資料 因此會有 childValue = this.propsValue
4.附元件的資料如為ajax取得 可透過v-if隔開
5.由子元件更新回父層為emit

###### tags: `vue` `JSX`