<div id="root">
    <table>
        <tbody>
            <row></row>
            <row></row>
            <row></row>
        </tbody>
    </table>
</div>
<script>
    Vue.component('row',{
        template:`<tr><td>this is a row</td></tr>`
    });
    var vm = new Vue({
        // el限制一个vue实例的管理范围。
        el:"#root",
    });
</script>看似上面代码书写没有什么问题,但是打开页面你会看到,如下图:

所有的tr标签都跑到了tbody外面,这是不符合规范的。
那么如何解决这个问题,通过is属性,只需要在原来代码改一下:
<div id="root">
    <table>
        <tbody>
            <tr is="row"></tr>
            <tr is="row"></tr>
            <tr is="row"></tr>
        </tbody>
    </table>
</div>原有的html实例不变,这样就可以避免tr标签上升到tbody标签外头了。
同样像ul(li),select(option)
<ul>
  <li is="row"></li>
  <li is="row"></li>
  <li is="row"></li>
</ul>
<select>
    <option is="row"></option>
    <option is="row"></option>
    <option is="row"></option>
</select>data在子组件中,必须为一个函数,同时函数有返回数据。
Vue.component('row',{
        data:function(){
            return {
                content:"this is content"
            }
        },
        template:`<tr><td>{{content}}</td></tr>`
    });Vue不建议在代码中操作DOM,但是在复杂动画效果,不操作DOM,光靠数据的绑定,是无法实现的。
<div id="app">
    <div ref="hw" @click="handleClick">hello world</div>
</div>
var app = new Vue({
        el:"#app",
        methods:{
            handleClick:function () {
                //指的是ref="hw"的DOM
                divDom = this.$refs.hw;
                console.log(divDom.innerHTML)
            }
        }
    })那么在组件中是如何应用ref,咱们定义一个计数功能:
<div id="root">
    <!-- 父组件监听change变化并交给 handleChange处理-->
    <counter @change="handleChange" ref="one"></counter>
    <counter @change="handleChange" ref="two"></counter>
    <div>{{total}}</div>
</div>Vue.component("counter",{
    template:`<div @click="handleClick">{{number}}</div>`,
    data:function () {
        return {
            number:0
        }
    },
    methods:{
        handleClick:function () {
            this.number ++;
            //子组件需要向父组件传递事件,当当前组件数据发生变化时。
            this.$emit('change')
        }
    }
});
var vm = new Vue({
    // el限制一个vue实例的管理范围。
    el:"#root",
    //total用来计算两个counter组件内数据的和
    data:{
        total:0
    },
    methods:{
        handleChange:function () {
            //total求和
            this.total = this.$refs.one.number + this.$refs.two.number
        }
    }
});父组件可以向子组件传递参数,但是子组件不能修改传递到子组件的参数,这就是单向数据流。
<div id="root">
    <!--1.父组件向子组件传递名字为count的值-->
    <counter :count="0"></counter>
    <counter :count="5"></counter>
</div>
var counter = {
    // 2.子组件定义props接收count
    data:function(){
        return {
            // 3.既然子组件无法修改父组件传来的参数
            // 那么number为复制传过来的参数,咱们使用number
            number:this.count
        }
    },
    props:['count'],
    // 4.子组件使用复制过来的number,
    template:`<div @click="handleClick">{{number}}</div>`,
    methods:{
        handleClick:function () {
            // 并且还可以更改复制的number
            this.number ++
        }
    }
};
var vm = new Vue({
    // el限制一个vue实例的管理范围。
    el:"#root",
    components:{
        counter:counter
    }
});
<div id="root">
    <!--1.父组件向子组件传递名字为count的值-->
    <!--监听inc事件,一旦触发执行父组件handleIncrease函数-->
    <counter :count="0" @inc="handleIncrease"></counter>
    <counter :count="5" @inc="handleIncrease"></counter>
    <div>{{total}}</div>
</div>
var counter = {
    // 2.子组件定义props接收count
    data:function(){
        return {
            // 3.既然子组件无法修改父组件传来的参数
            // 那么number为复制传过来的参数,咱们使用number
            number:this.count
        }
    },
    props:['count'],
    // 4.子组件使用复制过来的number,
    template:`<div @click="handleClick">{{number}}</div>`,
    methods:{
        handleClick:function () {
            // 并且还可以更改复制的number
            this.number ++;
            // 5.子组件通过触发事件,将触发的inc事件传递给父组件
            this.$emit('inc',1)
        }
    }
};
var vm = new Vue({
    // el限制一个vue实例的管理范围。
    el:"#root",
    data:{
      total:5,
    },
    components:{
        counter:counter
    },
    methods:{
        // 父组件定义函数
        handleIncrease:function (step) {
            // step 为子组件 $emit的第二个参数。
            this.total += step
        }
    }
});首先需要了解的是什么是props特性
props特性其实就是,在父组件中传入了参数,恰巧子组件在props也定义了该参数的校验规则。并且子组件能使用该参数在template进行渲染<child content="hell world"></child>
Vue.component('child',{
    // 子组件接收props
    props:{
        // 传入content的类型
        // 方式1:content:[String,Number]
        // 方式2:
        content:{
            type:String,//要求传入值类型
            required:false,//是否必填
            defaule:"default value",//默认值
            validator:function (value) {
                // 传入数据长度大于5
                return (value.length > 5)
            }
        }
    },
   template:`<div>Child</div>`
});
var vm = new Vue({
    el:"#root",
});非props特性
父组件向子组件传递的是一个属性,子组件并没有声明该属性定义的内容。
1.这样子组件就不能使用该属性在子组件template渲染。
2.那么该属性会在template定义的最外层标签的标签里,显示.e.g.: <div content="hello">hello</div>当给一个组件标签绑定一个事件其实是自定义事件,不会触发原生事件
<div id="root">
    <!--当给一个组件标签绑定一个事件其实是自定义事件,不会触发原生事件-->
    <child @click="handleClick"></child>
</div>
Vue.component("child",{
    // 在标签绑定事件时原生的事件
    template:"<div @click='handleClick'>Child</div>",
    methods:{
        //会触发
        handleClick:function () {
            alert("click click")
        }
    }
});
var vm = new Vue({
    el:"#root",
    methods:{
        // 不会触发
        handleClick:function () {
            alert("click")
        }
    }
});那么如何触发自定义事件?$emit
Vue.component("child",{
    // 在标签绑定事件时原生的事件
    template:"<div @click='handleClick'>Child</div>",
    methods:{
        //会触发
        handleClick:function () {
            //通过$emit触发自定义事件
            this.$emit("click")
        }
    }
});但是这样写代码冗余,过于繁琐?通过添加事件修饰符.native
<div id="root">
    <!--当给一个组件标签绑定一个事件其实是自定义事件,不会触发原生事件-->
    <!--通过添加.native将该事件转为原生click事件-->
    <child @click.native="handleClick"></child>
</div>
</body>
<script>
    Vue.component("child",{
        // 在标签绑定事件时原生的事件
        template:"<div>Child</div>",
    });
    var vm = new Vue({
        el:"#root",
        methods:{
            // 不会触发
            handleClick:function () {
                alert("click")
            }
        }
    });
</script>持续更新中.....
原文:https://www.cnblogs.com/xujunkai/p/12229983.html