半亩花田i
平时学习的笔记以及写的demo,仅供参考
posts - 65,comments - 2,views - 94458

gitHub地址:https://github.com/huangpna/vue_learn/example里面的lesson06

一 vue组件基本实例

 举个例子:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>app1</title>
</head>
<body>
    <div id="app1">
        <button-counter></button-counter>    <!--注意:点击按钮时,每个组件都会各自独立维护它的 count。因为你每用一次组件,就会有一个它的新实例被创建。-->
        <button-counter></button-counter>
        <button-counter></button-counter>
    </div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('button-counter',{   //全局注册一个组件
        data:function () {
            return {
                count:0
            }
        },
        template:'<div><button @click="count++">点击一下</button>&nbsp;&nbsp;&nbsp;&nbsp;<span>{{count}}</span></div>'
    });
    new Vue({el:'#app1'}); //创建一个vue实例
</script>
</html>
复制代码

 

 

(1)因为组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

(2)一个组建的data选项必须是一个函数,而不是像之前一样直接接受一个对象

(3)有两种注册注册组件的方式:全局注册和局部注册;至此,我们的注册都只是通过Vue.component全局注册的。

(4)全局注册的组件可以用在其被注册之后的任何 (通过 new Vue) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。

二 通过prop给子组件传递数据

举个例子:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>app1</title>
</head>
<body>
    <div id="app1">
        <button-counter title="My journey with Vue"></button-counter>          //通过自定义特性传递值
        <button-counter title="Blogging with Vue"></button-counter>
        <button-counter title="Why Vue is so fun"></button-counter>
    </div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('button-counter',{   //全局注册一个组件
        props:['title'],    //可以传递任何类型的值
        data:function () {
            return {
                count:0
            }
        },
        template:'<div><button @click="count++">点击一下</button>&nbsp;&nbsp;&nbsp;&nbsp;<span v-if="count == 1">{{title}}</span></div>'  //值显示,查看是否传递成功
    });
    new Vue({el:'#app1'}); //创建一个vue实例
</script>
</html>
复制代码

 

一个组件默认可以用过任意数量的prop,任何值都可以传递给任何 prop。在上述例子中,你会发现我们能够在组件实例中访问这个值,就像访问 data 中的值一样。

一个 prop 被注册之后,你就可以像上面例子一样把数据作为一个自定义特性传递进来。

例子2:

注意:这个时候我们想要给每篇博文渲染一个组件

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>app2</title>
    <style>
        #app2>div{
            width:800px;
            height:160px;
            background-color: #ff4225;
            font-size:35px;
            text-align:center;
            line-height:160px;
            margin:0 auto  20px;
        }
    </style>
</head>
<body>
    <div id="app2">
        <my-content v-for="item in dataList" v-bind:num="item.id" v-bind:title="item.title"></my-content>  <!--动态传递值-->
    </div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('my-content',{
        props:['title','num'],
        data:function () {

        },
        template:'<div>{{title}}------{{num}}</div>'
    });
    new Vue({
        el:'#app2',
        data:{
            dataList: [
                { id: 1, title: '博文组件' },
                { id: 2, title: '博文组件' },
                { id: 3, title: '博文组件' }
            ]
        }
    });
</script>
</html>
复制代码

 

但是很多时候我们的博文不止需要标题和内容,可能要传递的数据更多,这个时候组件就会变得越来越复杂,这个时候你可以变成只接受一个单独的dataList props。

注意:必须将组件模板包含在一个父元素内,否则会报错。

三 通过事件向父级组件发送消息

举个例子(假如说我们现在需要引入一个可访问性的功能来放大博文的字号):

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>app2</title>
    <style>
        #app2>div>div{
            width:800px;
            height:160px;
            background-color: #ff4225;
            text-align:center;
            line-height:160px;
            margin:0 auto  20px;
        }
    </style>
</head>
<body>
<div id="app2">
    <div :style="{fontSize:postFontSize + 'px'}">   <!--它可以在模板中用来控制所有博文的字号-->
        <my-content v-for="item in dataList" v-on:enlarge-text="changeFontSize" v-bind:num="item.id" v-bind:title="item.title"></my-content>
    </div>                                     <!--注意:然后我们用v-on 在博文组件上监听这个事件-->
</div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('my-content',{
        props:['title','num'],
        data:function () {

        },                                                                                  //但是有的时候我们需要抛出一个特定的值,可以通过$emit的第二个参数
        template:`<div>{{title}}------{{num}}------<button v-on:click="$emit('enlarge-text',0.5)">点击放大字体</button></div>`  //现在我们需要给每篇博文添加一个按钮来放大字号
    });           //注意:这个时候如果说我们需要点击这个按钮,需要调用内容的$emit方法并列入事件的名称来向父级组件触发一个事件
    new Vue({
        el:'#app2',
        data:{
            dataList: [
                { id: 1, title: '博文组件' },
                { id: 2, title: '博文组件' },
                { id: 3, title: '博文组件' }
            ],
            postFontSize: 20     //添加一个postFontSize数据属性来支持这个功能
        },
        methods:{
            changeFontSize:function ($event) {  //那么这个值将作为一个参数传入这个方法
                let _this = this;
                _this.postFontSize += $event;
            }
        }
    });
</script>
</html>
复制代码

 

 

注释:首先我们可以通过在父组件中添加一个postFontSize数据属性来支持这个功能,它可以在模板中用来控制所有博文的字号;然后我们需要给每篇博文添加一个按钮来放大字号,当点击这个按钮时,需要调用内容的$emit方法并列入事件的名称来向父级组件触发一个事件,然后我们需要用v-on 在博文组件上监听这个事件,但是有的时候我们需要抛出一个特定的值,可以通过$emit的第二个参数;如果这个事件处理函数是一个方法,那么这个值将作为一个参数传入这个方法。

四 在组件上使用v-model

举个例子:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>app3</title>
</head>
<body>
    <div id="app3">
        <div>
            <span>输入框1: </span>
            <input v-model="searchText">
        </div>
        <!--等价于-->
        <custom-input v-bind:value="searchText" v-on:input="getInputV"></custom-input>
    </div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('custom-input',{
        props:['value'],
        template:`<div><span>输入框2: </span><input v-bind:value="value" v-on:input="$emit('input',$event.target.value)"></div>`
    });
    new Vue({
        el:'#app3',
        data:{
            searchText:''
        },
        methods:{
            getInputV:function (v) {
                let _this = this;
                _this.searchText = v;
            }
        }
    })
</script>
</html>
复制代码

五 通过插槽分发内容

举个例子:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index4</title>
    <style>
        ._style{
            width:500px;
            height:220px;
            background-color: #ff4225;
        }
    </style>
</head>
<body>
    <div id="app4">
        <alert-box>
            Something bad happened.
        </alert-box>
    </div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('alert-box',{
        props:[],
        template:`<div class="_style"><span>Error!</span><slot></slot></div>`
    });
    new Vue({
        el:'#app4'
    })
</script>
</html>
复制代码

如你所见,我们只要在需要的地方加入插槽就行了——就这么简单!

六 动态组件

有时候在不同组件之间进行动态切换是非常有用的,举例说明:

复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index5</title>
    <style>
        .tab-button:hover{
            background: red;
        }
        #app5>.active{
            background: red;
        }
    </style>
</head>
<body>
    <div id="app5">
        <button v-for="item in navs" v-bind:key="item"  v-bind:class="['tab-button',{active:item === currentTab}]" v-on:click="tab(item)">
            {{item}}
        </button>
        <!-- 组件会在 `currentTabComponent` 改变时改变 -->
        <component v-bind:is="currentTabComponent"></component>
    </div>
</body>
<script src="../js/vue.min.js"></script>
<script>
    Vue.component('my-home',{
        template:'<div>Archive component111111</div>'
    });
    Vue.component('my-posts',{
        template:'<div>Archive component222222</div>'
    });
    Vue.component('my-archive',{
        template:'<div>Archive component333333</div>'
    });
    new Vue({
        el:'#app5',
        data:{
            currentTab:'Home',
            navs:['Home','Posts','Archive']
        },
        methods:{
            tab:function (v) {
                let _this = this;
                _this.currentTab = v;
            }
        },
        computed:{
            currentTabComponent:function () {
                let _this = this;
                return 'my-'+ _this.currentTab.toLowerCase();
            },
        }
    })
</script>
</html>
复制代码

在上述示例中,currentTabComponent 可以包括

  • 已注册组件的名字,或
  • 一个组件的选项对象

七 解析DOM模板时的注意事项

有些 HTML 元素,诸如 <ul><ol><table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。而有些元素,诸如 <li><tr> 和 <option>,只能出现在其它某些特定的元素内部。

这会导致我们使用这些有约束条件的元素时遇到一些问题。例如:

<table>
<blog-post-row></blog-post-row>
</table>

这个自定义组件 <blog-post-row> 会被作为无效的内容提升到外部,并导致最终渲染结果出错。幸好这个特殊的 is 特性给了我们一个变通的办法:

<table>
<tr is="blog-post-row"></tr>
</table>

需要注意的是如果我们从以下来源使用模板的话,这条限制是不存在的:

到这里,你需要了解的组件的基础用法就了解完了,接下来需要深入学习组件了。

posted on   半亩花田i  阅读(275)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示