how2j.cn

步骤 1 : 组件是什么   
步骤 2 : 局部组件   
步骤 3 : 全局组件   
步骤 4 : 参数   
步骤 5 : 动态参数   
步骤 6 : 自定义事件   
步骤 7 : 遍历 json 数组   
步骤 8 : 最开始效果步骤里的代码   

如效果所示,每个产品展示,就是一个模板。 只用做一个模板,然后照着这个模板,传递不同的参数就可以看到不同的产品展示了。

这个模板,就是组件。

当前看到的这个效果比较复杂,接下来会由浅入深,慢慢地把这个效果做出来。

注: 点击产品,还可以增加销售数量。 虽然业务上不会真的增加销售数量,但是这里是演示组件也有自定义事件的效果。
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } div.product:hover{ border:1px solid #c40000; } div.price{ color:#c40000; font-weight:bold; font-size:1.2em; margin:10px; } div.productName{ color:gray; font-size:0.8em; margin:10px; } div.sale{ float:left; width:100px; border:1px solid lightgray; border-width:1px 0px 0px 0px; color:gray; font-size:0.8em; padding-left:10px; } div.review{ overflow:hidden; border:1px solid lightgray; border-width:1px 0px 0px 1px; color:gray; font-size:0.8em; padding-left:10px; } </style> <div id="tempalate" style="display:none"> <div class="product" v-on:click="increaseSales"> <div class="price"> ¥ {{product.price}} </div> <div class="productName"> {{product.name}} </div> <div class="sale"> 月成交 {{product.sale}} 笔</div> <div class="review"> 评价 {{product.review}} </div> </div> </div> <div id="div1"> <product v-for="item in products" v-bind:product="item"></product> </div> <script> var tempalateDiv=document.getElementById("tempalate").innerHTML; var templateObject = { props: ['product'], template: tempalateDiv, methods: { increaseSales: function () { this.product.sale = parseInt(this.product.sale); this.product.sale += 1 this.$emit('increment') } } } Vue.component('product', templateObject) new Vue({ el: '#div1', data:{ products:[ {"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","price":"889","sale":"18","review":"5"}, {"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","price":"322","sale":"35","review":"12"}, {"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","price":"523","sale":"29","review":"3"}, ] } }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
接下来就由浅入深地展开组件的学习。 先看最简单的局部组件。
在 Vue对象里增加 components:

components:{
'product':{
template:'<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'
}

然后在视图里,通过如下方式就可以调用了

<product></product>

如果想重复使用,则多写几次就行了

<product></product>
<product></product>
<product></product>
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } </style> <div id="div1"> <product></product> <product></product> <product></product> </div> <script> new Vue({ el: '#div1', components:{ 'product':{ template:'<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>' } } }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
和vue.js 里的过滤器一样,有的组件会在不同页面使用,这个时候就可以考虑用全局组件。

Vue.component('product', {
template: '<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'
})

写法其实跟局部差不多,只是提出来了。 这样到处都可以用了。
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } </style> <div id="div1"> <product></product> <product></product> <product></product> </div> <script> Vue.component('product', { template: '<div class="product" >MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>' }) new Vue({ el: '#div1' }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
像前面的例子,产品名称都是固定的,这样肯定不行,所以就要能够传递参数给组件。
设置参数name, 并且在组件里使用这个name:

Vue.component('product', {
props:['name'],
template: '<div class="product" >{{name}}</div>'
})

调用的时候,就当作是一个自定义属性传进去就可以了

<product name="MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮"></product>
<product name="宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包"></product>
<product name="唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮"></product>
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } </style> <div id="div1"> <product name="MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮"></product> <product name="宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包"></product> <product name="唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮"></product> </div> <script> Vue.component('product', { props:['name'], template: '<div class="product" >{{name}}</div>' }) new Vue({ el: '#div1' }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
所谓的动态参数,就是指组件内的参数可以和组件外的值关联起来
如效果所示,在组件外的input输入数据,就可以传递到组件内了
关键是这一行,name表示组件内的属性name, outName就是组件外的

<product v-bind:name="outName"></product>
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } </style> <div id="div1"> 组件外的值:<input v-model="outName" ><br> <product v-bind:name="outName"></product> </div> <script> Vue.component('product', { props:['name'], template: '<div class="product" >{{name}}</div>' }) new Vue({ el: '#div1', data:{ outName:'产品名称' } }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
增加自定义事件和在一个Vue对象上增加 methods 是一样的做法
先来个methods:

methods:{
increaseSale:function(){
this.sale++
}
}

然后在组件里:

v-on:click="increaseSale"

,这里是在组件上增加的,而不是在视图上增加的。
测试: 点击产品,就会增销量
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } </style> <div id="div1"> <product name="MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮" sale="10" ></product> <product name="宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包" sale="20" ></product> <product name="唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮" sale="30" ></product> </div> <script> Vue.component('product', { props:['name','sale'], template: '<div class="product" v-on:click="increaseSale">{{name}} 销量: {{sale}} </div>', methods:{ increaseSale:function(){ this.sale++ } } }) new Vue({ el: '#div1' }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
步骤 7 :

遍历 json 数组

edit
大部分时候是拿到一个 json 数组,然后遍历这个 json 数组为多个组件实例。
1. 首先准备产品数组

products:[
{"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","sale":"18"},
{"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","sale":"35"},
{"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","sale":"29"}
]

2. 然后在视图里通过 v-for 遍历 products

<product v-for="item in products" v-bind:product="item"></product>

3. 接着修改组件,让接受的参数为 v-bind:product 里的这个 product,显示和方法里也通过 product.xxx 来调用。

Vue.component('product', {
props:['product'],
template: '<div class="product" v-on:click="increaseSale">{{product.name}} 销量: {{product.sale}} </div>',
methods:{
increaseSale:function(){
this.product.sale++
}
}
})
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } </style> <div id="div1"> <product v-for="item in products" v-bind:product="item"></product> </div> <script> Vue.component('product', { props:['product'], template: '<div class="product" v-on:click="increaseSale">{{product.name}} 销量: {{product.sale}} </div>', methods:{ increaseSale:function(){ this.product.sale++ } } }) new Vue({ el: '#div1', data:{ products:[ {"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","sale":"18"}, {"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","sale":"35"}, {"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","sale":"29"} ] } }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果
步骤 8 :

最开始效果步骤里的代码

edit
最开始效果步骤里的代码其实就是在前面的基础上,增加了一些样式,增加了一些字段而已。
另外 template 部分因为比较复杂,就不好写在一个 单引号 ' ' 里维护起来,所以就直接写在html里,然后通过html dom 获取出来,这样编写起来略微容易一点。

var tempalateDiv=document.getElementById("tempalate").innerHTML;

其他的就没有什么新东西啦
运行效果
<script src="https://how2j.cn/study/vue.min.js"></script> <style> div.product{ float:left; border:1px solid lightGray; width:200px; margin:10px; cursor: pointer; } div.product:hover{ border:1px solid #c40000; } div.price{ color:#c40000; font-weight:bold; font-size:1.2em; margin:10px; } div.productName{ color:gray; font-size:0.8em; margin:10px; } div.sale{ float:left; width:100px; border:1px solid lightgray; border-width:1px 0px 0px 0px; color:gray; font-size:0.8em; padding-left:10px; } div.review{ overflow:hidden; border:1px solid lightgray; border-width:1px 0px 0px 1px; color:gray; font-size:0.8em; padding-left:10px; } </style> <div id="tempalate" style="display:none"> <div class="product" v-on:click="increaseSales"> <div class="price"> ¥ {{product.price}} </div> <div class="productName"> {{product.name}} </div> <div class="sale"> 月成交 {{product.sale}} 笔</div> <div class="review"> 评价 {{product.review}} </div> </div> </div> <div id="div1"> <product v-for="item in products" v-bind:product="item"></product> </div> <script> var tempalateDiv=document.getElementById("tempalate").innerHTML; var templateObject = { props: ['product'], template: tempalateDiv, methods: { increaseSales: function () { this.product.sale = parseInt(this.product.sale); this.product.sale += 1 this.$emit('increment') } } } Vue.component('product', templateObject) new Vue({ el: '#div1', data:{ products:[ {"name":"MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮","price":"889","sale":"18","review":"5"}, {"name":"宾度 男士手包真皮大容量手拿包牛皮个性潮男包手抓包软皮信封包","price":"322","sale":"35","review":"12"}, {"name":"唯美诺新款男士手包男包真皮大容量小羊皮手拿包信封包软皮夹包潮","price":"523","sale":"29","review":"3"}, ] } }) </script>


源代码
1. 双击选中单词 2. 三击选中整行 3. CTRL+F 查找 4. F8 全屏编辑,再次点击恢复
渲染中 渲染完成
效果


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2023-12-07 并没有观察到在步骤3里提到的可以“在不同页面使用”
Shu_Enryu




RT 我觉得站长想表达的应该是“在同一个页面,不同的与Vue对象进行绑定的元素,可以使用这个全局组件。”
<style>
    div.product{
      display: inline-block;
      border:1px solid lightGray;
      width:200px;
      margin:10px;
      cursor: pointer;
    }
</style>
<html>
    <head>
        <script src="https://how2j.cn/study/vue.min.js"></script>
    </head>
    <body>
        <div id="div1">
            <product></product>
            <product></product>
            <product></product>
        </div>
        <div>
            
        </div>
        <div id="div2">
            <product></product>
            <product></product>
            <product></product>
            <product></product>
        </div>

    </body>
    <script>
        Vue.component('product', {
            template: '<div class="product">MAXFEEL休闲男士手包真皮手拿包大容量信封包手抓包夹包软韩版潮</div>'});
        new Vue({
            el: "#div1"
        });
        new Vue({
            el: "#div2"
        });
    </script>
</html>

							





回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2022-11-22 那个组件里的props['name'] 是干嘛的
言宇成a

那个组件里的props['name'] 是干嘛的,有点不懂,删除了又跑不动




1 个答案

endeavour_tsx
答案时间:2023-07-02
肯定不能删啊,这个是往你定义的组件内传递数据,相当于从vue对象中每次遍历出的item传递到product中,v-bind:product="item"



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2022-03-30 没看懂局部和全局区别
2020-08-16 谢谢站长!网页的演示部分,被调得太窄了
2020-04-13 this.$emit('increment') 这个是干啥的?


提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 11 条以前的提问,请 点击查看

提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 前端部分-Vue.js-组件 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图