vue使用组件

使用组件的细节:

细节一:子组件的基本使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中组件使用的细节1</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <table>
        <tbody>
            <tr is="row"></tr>
            <tr is="row"></tr>
            <tr is="row"></tr>
        </tbody>
    </table>
</div>
<script>
    Vue.component('row',{
        template: `<tr><td>this is row</td></tr>`
    })
    var vm = new Vue({
        el : '#root',
    })
</script>
</body>
</html>

 细节二:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中组件使用的细节1</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <table>
        <tbody>
            <tr is="row"></tr>
            <tr is="row"></tr>
            <tr is="row"></tr>
        </tbody>
    </table>
</div>
<script>
    Vue.component('row',{
        //子组件中的数据 data 需要用函数来表示 函数返回一个对象
        data: function (){
            return {
                name : '小明'
            }
        },
        template: `<tr><td>{{name}}</td></tr>`
    })
    var vm = new Vue({
        el : '#root',
    })
</script>
</body>
</html>

 ref 的用法:vue中使用 ref 获取 dom 节点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中组件使用的细节1</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <div
        ref="hello"
        @click="fun"
    >hello world</div>
</div>
<script>
    var vm = new Vue({
        el : '#root',
        methods : {
            fun : function(){
                alert(this.$refs.hello.innerHTML)
            }
        }
    })
</script>
</body>
</html>
弹出了 指定div 的内容 hello world

 ref 综合案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中组件使用的细节1</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <counter ref="one" @change="handleChange"></counter>
    <counter ref="two" @change="handleChange"></counter>
    <div>{{total}}</div>
</div>
<script>
    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 : '#root',
        data : {
            total : 0
        },
        methods : {
            handleChange : function(){
                this.total = this.$refs.one.number + this.$refs.two.number
            }
        }
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中组件使用的细节1</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <counter ref="one" @change="handleChange"></counter>
    <counter ref="two" @change="handleChange"></counter>
    <div>{{total}}</div>
</div>
<script>
    let count ={
        template: `<div @click="handleClick">{{number}}</div>`,
        data: function () {
            return{
                number : 0
            }
        },
        methods: {
            handleClick : function(){
                this.number++;
                this.$emit('change')
            }
        }
    }
    var vm = new Vue({
        el : '#root',
        data : {
            total : 0
        },
        components:{
          counter : count // 子组件
        },
        methods : {
            handleChange : function(){
                this.total = this.$refs.one.number + this.$refs.two.number
            }
        }
    })
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父子组件传值</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <counter :count="1" @change="handleChange"></counter>
    <counter :count="2" @change="handleChange"></counter>
    <div>{{total}}</div>
</div>
<script>
    //父组件向子组件传值 子组件不能直接修改父组件传递的值
    // 可以定义一个属性存放父组件传递的值 然后进行修改自己定义的属性
    let counter = {
        props : ['count'],
        template : `<div @click="hendleClick">{{number}}</div>`,
        data : function(){
            return {
                number : this.count
            }
        },
        methods : {
            hendleClick : function(){
                this.number = this.number + 2;
                this.$emit('change',2);//向外触发一个自定义事件 第二个参数改变的步长
            }
        }
    }
    let vm = new Vue({
        el:'#root',
        data:{
          total: 3
        },
        components:{
            counter : counter, //子组件
        },
        methods : {
            handleChange : function(step){ //参数为监听事件传出的步长
                this.total += step
            }
        }
    })
</script>
</body>
</html>
以上三个案例的结果一样: 点击前两个数字会自加1 触发第三个数字改变  第三个数字等于前两个数字的和 (不同的是子组件的写法不同)
ref 练习:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>父子组件传值</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <one ref="one" :count="1" @first="Change"></one>
    <two ref="two" :count="2" @second="Change"></two>
    <div>{{total}}</div>
</div>
<script>
    let one = {
        props : ['count'],
        template : `<div @click="hendleClick">{{number}}</div>`,
        data : function(){
            return {
                number : this.count
            }
        },
        methods : {
            hendleClick : function(){
                this.number = this.number + 2;
                this.$emit('first',2);
            }
        }
    }
    let two = {
        props : ['count'],
        template : `<div @click="hendleClick">{{number}}</div>`,
        data : function(){
            return {
                number : this.count
            }
        },
        methods : {
            hendleClick : function(){
                this.number = this.number + 3;
                this.$emit('second',3);
            }
        }
    }
    let vm = new Vue({
        el:'#root',
        data:{
            total: 3
        },
        components:{
            one : one,
            two : two
        },
        methods : {
            Change : function(){
                this.total = this.$refs.one.number + this.$refs.two.number
            }
        }
    })
</script>
</body>
</html>

 组件参数校验:

需求:校验父组件传递过来的必须是个字符串

<div id='root'>
  <child content='hello world'></child>
</div>

<script>
Vue.component('child',{
  props:{
    content:String
  },
  template:'<div>{{content}}</div>'
})
var vm = new Vue({
  el:'#root'
})
</script>

 将接收的props定义成对象,并指定类型,不以数组的形式接收参数

 接收的数据是字符串类型 或者 数字类型都可以
props:{
  content:[String, Number]
}

 复杂的校验:

<div id='root'>
  <child content='hello world'></child>
</div>

<script>
Vue.component('child',{
  props:{
    content:{
      type:String,//数据类型
      required:false,//是否是必传
      default:'default content',//如果没传值,默认值
      validator:function(val){//自定义校验器,数据长度必须 > 5 参数为传入的数据
        return (val.length>5)
      }
    }
  },
  template:'<div>{{content}}</div>'
})
var vm = new Vue({
  el:'#root'
})
</script>

非props特性

父组件向子组件传递参数,子组件没有props这块内容,所以就会报错,不去接收,就没法使用这个content
第二个特点是,子组件没接收,对应的属性值会显示在标签中,props特性不会显示

Vue给组件绑定原生事件:组件生成的元素绑定原生事件需要在事件的后面加上native

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue给组件绑定原生事件</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <child @click.native="handleClick"></child>组件生成的元素绑定原生事件需要在事件的后面加上native
</div>
<script>
    Vue.component('child',{
        template : `<div>Child</div> `
    })
    let vm = new Vue({
        el : '#root',
        methods : {
            handleClick : function(){
                alert('click')
            }
        }
    })
</script>
</body>
</html>

非父子组件间的传值(如何在vue重使用 bus/总线/发布订阅模式/观察者模式):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>非父子组件之间的传值(bus/总线/发布订阅模式/观察者模式)</title>
    <script src="./vue.js"></script>
</head>
<body>
    <div id="root">
        <child content="Dell"></child>
        <child content="Lee"></child>
    </div>
    <script>
        //在vue的原型链上挂载一个bus的属性 只要之后调用new Vue()或者创建组件 每一个组件都会有bus这个属性
        Vue.prototype.bus = new Vue();
        Vue.component('child',{
            props : {
                content : String
            },
            data : function(){
                return {
                    selfContent : this.content
                }
            },
            template : `<div @click="hendleClick">{{selfContent}}</div>`,
            methods : {
                hendleClick : function(){
                    this.bus.$emit('change',this.selfContent)
                }
            },
            //借助生命周期钩子监听bus的改变
            mounted : function(){
                this.bus.$on('change',(msg) => {
                    this.selfContent = msg;
                })
            }
        })
        let vm = new Vue({
            el : '#root',
        })
    </script>
</body>
</html>

vue中的插槽:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中的插槽</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <child>
        <!--需要插槽才能渲染的内容-->
        <p>Dell</p>
        <p>Lee</p>
    </child>
</div>
<script>
    //slot语法:slot标签显示的内容是父组件向子组件插入的内容 插槽 也就是上面的 child 标签包住的 p 标签
    //slot中可以放置默认内容 当父组件没有传入内容则显示默认内容
    Vue.component('child',{
        template : `<div>
                        <p>hello</p>
                        <slot><p>默认内容,当子组件没有传如任何内容时默认显示</p></slot>
                    </div>`,
    })
    let vm = new Vue({
        el : '#root',
    })
</script>
</body>
</html>
假如使用多个插槽的时候,就需要用具名插槽:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中的插槽</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <child>
        <div slot="footer">footer</div>
    </child>
</div>
<script>
    Vue.component('child',{
        template : `<div>
                        <slot name="header">
                            <h1>default header</h1>
                        </slot>
                        <div>content</div>
                        <slot name="footer"></slot>
                    </div>`,
    })
    let vm = new Vue({
        el : '#root',
    })
</script>
</body>
</html>

   作用域插槽:作用域插槽必须是由template标签包起来的 并且插槽要声明从子组件接收的数据放在哪(slot-scope) 以及告诉子组件模板的信息(接收到的数据应该怎么展示)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>作用域插槽</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <child>
        <template slot-scope="props"><!--定义一个插槽,该插槽必须放在template标签内-->
            <em>{{props.item}}</em><!--定义使用渲染方式-->
        </template>
    </child>
    <child>
        <template slot-scope="props">
            <h1>{{props.item}}</h1><!--定义不同的渲染方式-->
        </template>
    </child>
</div>
<script>
    let count = {
        data : function(){
            return {
                list : [1, 2, 3, 4]
            }
        },
        template : `<div>
                         <slot v-for="item of list" :item=item></slot>
                    </div>`
    }
    let vm = new Vue({
        el : '#root',
        components : {
            child : count
        }
    })
</script>
</body>
</html>

动态组件案例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue中的动态组件</title>
    <script src="./vue.js"></script>
</head>
<body>
<div id="root">
    <component :is="type"></component>
    <button @click="handlechange">change</button>
</div>
<script>
    //v-once指令 对数据进行缓存 提高性能
    let childone = {
        template : `<div v-once>child-one</div>`
    }
    let childtwo = {
        template : `<div v-once>child-two</div>`
    }
    let vm = new Vue({
        el : '#root',
        data : {
            type: childone
        },
        methods : {
            handlechange : function(){
                this.type === childone ? this.type=childtwo : this.type=childone
            }
        }
    })
</script>
</body>
</html>
原文地址:https://www.cnblogs.com/rickyctbur/p/11515705.html