Vue的组件

  1. 云栖社区>
  2. 博客>
  3. 正文

Vue的组件

slashboywang 2018-08-25 21:13:00 浏览757
展开阅读全文

1、组件的概念

组件(Component)是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。组件系统让我们可以用独立可复用的小组件来构建大型应用,几乎任意类型的应用的界面都可以抽象为一个组件树

2、全局组件的注册(所有实例都能用)

注册一个全局组件语法格式如下:

  • Vue.component(tagName, options)
    tagName 为组件名,options 为配置选项。
  • 注册后,我们可以使用以下方式来调用组件:
    <tagName></tagName>
<div id="app">
    app<runoob></runoob>
</div>
<div id="app1">
    app1<runoob></runoob>
</div>
<script>
    // 注册全局组件runoob
    Vue.component('runoob', {
        template: '<h1>自定义全局组件!</h1>'
    });
    // 创建Vue根实例
    new Vue({
        el: '#app'
    });
    new Vue({
        el:'#app1'
    })
</script>

3、局部组件的注册

  • 我们也可以在实例选项中注册局部组件,这样组件只能在这个实例中使用
<div id="app">
    app<runoob></runoob>
</div>
<div id="app1">
    app1<runoob></runoob>
</div>
<script>
    let Child = {
        template: '<h1>自定义组件!</h1>'
    };
    // 创建Vue根实例
    new Vue({
        el: '#app',
        components: {
            // <runoob> 将只在父模板可用
            'runoob': Child
        }
    });
    new Vue({
        el:'app1'
    })
</script>

4、父子组件通信(props)

  • prop 是父组件用来传递数据的一个自定义属性。
    父组件的数据需要通过 props 把数据传给子组件,子组件需要显式地用 props 选项声明 "prop":
  • 注意: prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
<div id="app">
    <parent></parent>
</div>
<script>
    let child = {
        template: `<div><p>这是个子组件{{name}}</p></div>`,
        // 声明 props
        props: ["name"]
    };
    let parent = {
        //模板
        template: `<div>
                    <h1>这是个父组件</h1>
                    <child :name="username"></child>
                    </div>`,
        //注册一个子组件
        components: {
            child: child
        },
        data() {
            return {
                username: "peiqi"
            }
        }
    };
    //创建Vue根实例
    const app = new Vue({
        el: "#app",
        //注册一个局部组件parent
        components: {
            parent: parent
        }
    })
</script>
  • 动态 Props
    类似于用 v-bind 绑定 HTML 特性到一个表达式,也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
<div id="app">
    <div>
      <input v-model="parentMsg">
      <br>
      <child v-bind:message="parentMsg"></child>
    </div>
</div>
 
<script>
// 注册
Vue.component('child', {
  // 声明 props
  props: ['message'],
  // 同样也可以在 vm 实例中像 "this.message" 这样使用
  template: '<span>{{ message }}</span>'
})
// 创建根实例
new Vue({
  el: '#app',
  data: {
    parentMsg: '父组件内容'
  }
})
</script>
  • 以下实例中将 v-bind 指令将 todo 传到每一个重复的组件中:
<div id="app">
    <ol>
    <todo-item v-for="item in sites" v-bind:todo="item"></todo-item>
      </ol>
</div>
 
<script>
Vue.component('todo-item', {
  props: ['todo'],
  template: '<li>{{ todo.text }}</li>'
})
new Vue({
  el: '#app',
  data: {
    sites: [
      { text: 'Runoob' },
      { text: 'Google' },
      { text: 'Taobao' }
    ]
  }
})
</script>

5、子父组件通信

  • 上面我们说过,props 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来。
  • 那么想一下子父通信怎么实现呢?
    机智如你发现:给子组件绑定事件,通过$emit将事件提交(可以携带参数),在父组件中绑定对应事件的处理函数就可以实现子父组件的通信了。
<div id="app">
    <parent></parent>
</div>
<script>
    // 子组件 提交一个事件 可以携带值
    let child = {
        template: `<div>
                        <p>这是个子组件</p>
                        <button @click="on_click">点我显示你银行卡余额</button>
                    </div>`,
        methods: {
            on_click: function () {
                //提交一个事件 可以携带值
                this.$emit("show_balance", this.balance)
            }
        },
        data() {
            return {
                balance: 998,
            }
        }
    };
    let parent = {
        template: `<div>
                    <h1>这是个父组件</h1>
                    <child @show_balance="my_func"></child>
                      <span>{{p_balance}}</span>
                    </div>`,
        //注册一个子组件
        components: {
            child: child
        },
        data() {
            return {
                username: "peiqi",
                p_balance: ""
            }
        },
        methods: {
            my_func: function (data) {
                this.p_balance = data
            }
        }
    };
    //创建Vue根实例
    const app = new Vue({
        //制定作用域
        el: "#app",
        //注册一个局部组件
        components: {
            parent: parent
        }
    })
</script>

6、非父子组件通信

  • 非父子组件的通信没有办法通过绑定事件来解决了,那就需要通过生成一个中间Vue实例来做父子组件通信的媒介,一个时间通过 Vue实例.emit()将事件提交到媒介实例,然后另一个组件通过 Vue实例.on()去处理传来的事件就可以完成两个互不相干的组件之间的通信了。
  • 只要思想不滑坡,方法总比问题多!!!
<div id="app">
    <alex></alex>
    <wenzhou></wenzhou>
</div>
<script>
    //生成一个中间Vue实例用于数据传递
    let Event = new Vue();
    let alex = {
        template: `<div>
                    <p>Alex</p>
                    //绑定事件
                    <button @click="on_click">点我给文周降薪</button>
                    </div>`,
        methods: {
            on_click: function () {
                //提交事件、传递参数
                Event.$emit("alex_said", this.money)
            }
        },
        //必须是这种return的数据形式
        data() {
            return {
                money: 10000,
            }
        }
    };
    let wenzhou = {
        template: `<div>
                        <p>哪吒</p>
                        {{wz_money}}
                    </div>`,
        // 加载结束后执行的
        mounted() {
            let that = this;
            Event.$on("alex_said", function (data) {
                that.wz_money = data;
                console.log(this)
            })
        },
        data() {
            return {
                wz_money: "",
            }
        }
    };
    //创建Vue根实例
    const app = new Vue({
        //制定作用域
        el: "#app",
        //注册两个局部组件
        components: {
            alex: alex,
            wenzhou: wenzhou,
        }
    })
</script>

7、mixins重复代码封装,类似于django中的母板

<div id="app">
    <popup></popup>
    <tip></tip>
</div>

<script>
    let base = {
        methods: {
            on_show: function () {
                this.show = true
            },
            on_hide: function () {
                this.show = false
            }
        },
        data() {
            return {
                show: false
            }
        }
    };
    let popup = {
        template: `<div>
                        <button @click="on_show">点我显示</button>
                        <button @click="on_hide">点我隐藏</button>
                        <p v-show="show">这是popup</p>
                   </div>`,
        mixins: [base],
        data() {
            return {
                show: true
            }
        }
    };
    let tip = {
        template: `<div>
                    <button v-on="{mouseenter: on_show, mouseleave: on_hide}">鼠标移入提示信息</button>
                    <p v-show="show">这是一个提示信息</p>
                </div>`,
        mixins: [base]
    };
    const app = new Vue({
        el: "#app",
        components: {
            popup: popup,
            tip: tip,
        }
    })
</script>

8、slot插槽

<div id="app">
    <test>
        <div slot="title"> 这是一个标题</div>
        <div slot="footer">这是底部</div>
    </test>
</div>
<template id="panel-tpl">
    <div>
        <slot name="title">1</slot>
        <hr>
        <slot name="content">2</slot>
        <hr>
        <slot name="footer">3</slot>
    </div>
</template>
<script>
    let test = {
        template: "#panel-tpl"
    };
    const app = new Vue({
        el: "#app",
        components: {
            test: test
        }
    })
</script>

网友评论

登录后评论
0/500
评论
slashboywang
+ 关注