Vue2 基础三组件化开发

代码下载

组件 (Component) 是 Vue.js 最强大的功能之一,组件可以扩展 HTML 元素,封装可重用的代码。

组件注册

全局注册:

        Vue.component(组件名称, {data: 组件数据,template: 组件模板内容});// 全局组件Vue.component('button-counter', {data: function() {return { count: 0 };},template: `<button @click="handle" v-text="'点击了(' + count + ')次'"></button>`,methods: {handle: function() {console.log(this.count);this.count++;}}});

全局注册:只能在当前注册它的vue实例中使用

        let vm = new Vue({el: '#app',data: {},// 局部组件components: {'myComponent': {data: function() {return { msg: 'hello' };},template: `<div v-text='msg'></div>`}}});

组件使用:

        <h3>全局组件</h3><button-counter></button-counter><h3>局部组件</h3><my-component></my-component>

注意事项:

  • data必须是一个函数。
  • 组件模板内容必须是单个跟元素,组件模板内容可以是模板字符串,模板字符串需要浏览器提供支持(ES6语法)。
  • 组件命名方式有短横线方式(Vue.component('my-component', { /* ... */ })),驼峰方式(Vue.component('myComponent', { /* ... */ }))但是必须使用短横线的方式使用组件。

Vue调试工具vue-devtools

安装

  • 打开终端,进入指定目录,执行mkdir 文件夹名命令创建文件夹。
  • 执行cd 文件夹名进入刚创建的文件夹目录,执行npm install vue-devtools命令开始下载(前提:安装node.js)。
  • 下载完成后,进入该文件下的 node_modules 文件,进入 vue-devtools 此文件夹,将其中vender 文件夹下的 manifest.json文件 进行编辑,修改 persistent 为 true 保存。
  • 打开浏览器找到扩展程序(以谷歌为例),并勾选开发者模式,点击出现的“加载扩展程序”按钮,最后选择vender 文件,重启浏览器就可以使用了。

编写如下代码,谷歌浏览器打开,打开开发者工具,选择“vue”,即可使用了:

<body><div class="main"><h2>调试工具(vue-devTools)</h2><div id="app"><div v-text="root"></div><first-com></first-com></div></div><script src="../js/vue.js"></script><script>Vue.component('first-com', {data: function() {return { first: '一级组件' }},template: `<div><div v-text='first'></div><second-com></second-com></div>`});Vue.component('second-com', {data: function() {return { second: '二级组件' }},template: `<div v-text='second'></div>`});let vm = new Vue({el: '#app',data: {root: '顶层根组件'}});</script>
</body>

请添加图片描述

组件间数据交互

父组件向子组件传值

  • 父组件发送的形式是以属性的形式绑定值到子组件身上。
  • 然后子组件用属性props接收。
  • 在props中使用驼峰形式,模板中需要使用短横线的形式,字符串形式的模板中没有这个限制。
<body><div class="main" id="app"><h2>父组件向子组件传值</h2><son-com :parent-title="title" :parent-content="content"></son-com></div><script src="../js/vue.js"></script><script>let vm = new Vue({el: '#app',data: {title: '标题',content: '内容'},components: {'son-com': {props: ['parentTitle', 'parentContent'],data: function() {return { info: '我的信息' }},template: `<div v-text="'title: ' + parentTitle + 'content: ' + parentContent + 'info: ' + info"></div>`}}});</script>
</body>

props属性值类型有字符串 String、数值 Number、布尔值 Boolean、数组 Array、对象 Object;通过v-bind传递数据类型为其自身类型,直接属性赋值则为字符类型。

        <type-com :pstr="123" :pnum="123" :pbool="true" :parr="[1, 2, 3]" :pobj="{ a: '123', b: '456' }"></type-com><type-com pstr="123" pnum="123" pbool="true" parr="[1, 2, 3]" pobj="{ a: '123', b: '456' }"></type-com>components: {'type-com': {props: ['pstr', 'pnum', 'pbool', 'parr', 'pobj'],template: `<div><div v-text='typeof pstr'></div><div v-text='typeof pnum'></div><div v-text='typeof pbool'></div><div v-text='typeof parr'></div><div v-text='typeof pobj'></div></div>`}}// number// number// boolean// object// object// string// string// string// string// string

子组件向父组件传值

  • 子组件用 $emit() 自定义事件,第一个参数为 自定义的事件名称 第二个参数为需要传递的数据
  • 父组件用v-on监听子组件的事件
<body><div class="main" id="app"><h2>子组件向父组件传值</h2><div :style="{fontSize: fontSize + 'px'}">父组件内容</div><son-com :data="info" :size="fontSize" @large-text="handle"></son-com></div><script src="../js/vue.js"></script><script>let vm = new Vue({el: '#app',data: {info: ['萝卜', '白菜', '土豆'],fontSize: 18},components: {'son-com': {props: ['data'],data: function() {return { size: '' }},template: `<div><ul><li :key='index' v-for='(value, index) in data' v-text='value'></li></ul><input type='text' v-model.number='size'><button @click='$emit("large-text", size)'>增加字号</button></div>`}},methods: {handle: function(v) {console.log('value: ', v);this.fontSize += v;console.log(this.fontSize);}}})</script>
</body>

兄弟组件的传值

  • 兄弟组件传递数据需要借助于事件中心,通过事件中心传递数据,提供事件中心 var hub = new Vue()
  • 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
  • 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
  • 销毁事件通过hub.$off()方法名,销毁之后无法进行传递数据
<body><div class="main" id="app"><h2>兄弟组件传值</h2><div><one-com></one-com><two-com></two-com><button @click="destroy">销毁</button></div></div><script src="../js/vue.js"></script><script>// 事件中心let hub = new Vue();// 组件oneVue.component('one-com', {data: function() {return { count: 0 };},template: `<div><div v-text='"one: " + count'></div><button @click='handle'>点击</button></div>`,methods: {handle: function() {// 触发事件hub.$emit('one-event', 1);}},mounted: function() {// 监听事件hub.$on('two-event', (v) => {this.count += v;});}});// 组件twoVue.component('two-com', {data: function() {return { count: 0 };},template: `<div><div v-text='"two: " + count'></div><button @click='handle'>点击</button></div>`,methods: {handle: function() {hub.$emit('two-event', 2);}},mounted: function() {hub.$on('one-event', (v) => {this.count += v;});}});let vm = new Vue({el: '#app',data: {},methods: {destroy: function() {hub.$off('one-event');hub.$off('two-event');}}});</script>
</body>

组件插槽

插槽可以为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。举例来说,这里有一个 组件,可以像这样使用:

<FancyButton>Click me! <!-- 插槽内容 -->
</FancyButton>

而 的模板是这样的:

<button class="fancy-btn"><slot></slot> <!-- 插槽出口 -->
</button>

元素是一个插槽出口 (slot outlet),标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。
image

最终渲染出的 DOM 是这样:

<button class="fancy-btn">Click me!</button>

默认内容

在外部没有提供任何内容的情况下,可以为插槽指定默认内容。比如模板是这样的一个组件:

<button type="submit"><slot>Submit <!-- 默认内容 --></slot>
</button>

具名插槽

组件中包含多个插槽出口是很有用,对于这种场景,<slot> 元素可以有一个特殊的 attribute name,用来给各个插槽分配唯一的 ID。举例来说,在一个 <BaseLayout> 组件中以确定每一处要渲染的内容:

<div class="container"><header><slot name="header"></slot></header><main><slot></slot></main><footer><slot name="footer"></slot></footer>
</div>

这类带 name 的插槽被称为具名插槽 (named slots)。没有提供 name<slot> 出口会隐式地命名为“default”。

在父组件中需要一种方式将多个插槽内容传入到各自目标插槽的出口,此时就需要用到具名插槽了。要为具名插槽传入内容,需要使用一个含 v-slot 指令的 <template> 元素,并将目标插槽的名字传给该指令,v-slot 有对应的简写 #,因此 <template v-slot:header> 可以简写为 <template #header>。其意思就是“将这部分模板片段传入子组件的 header 插槽中”:
image

        <base-layout><template v-slot:header><h4>页眉</h4></template><template v-slot:default><p>主体1</p><p>主体2</p></template><template #footer><p>页脚</p></template></base-layout>

当一个组件同时接收默认插槽和具名插槽时,所有位于顶级的非 <template> 节点都被隐式地视为默认插槽的内容。所以上面也可以写成:

        <base-layout><template v-slot:header><h4>页眉</h4></template><p>主体1</p><p>主体2</p><template #footer><p>页脚</p></template></base-layout>

也可以通过slot属性来指定, 这个slot的值必须和下面slot组件得name值对应上,如果没有匹配到则放到匿名的插槽中:

        <base-layout><h4 slot="header">页眉</h4><p>主体1</p><p>主体2</p><p slot="footer">页脚</p></base-layout>

作用域插槽

在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点,需要一种方法来让子组件在渲染时将一部分数据提供给插槽。确实有办法这么做!可以像对组件传递 props 那样,向一个插槽的出口上传递 attributes

<div><slot :text='"你好"' v-bind:count='1'></slot>
</div>

当需要接收插槽 props 时,默认插槽和具名插槽的使用方式有一些小区别。先展示默认插槽如何接受 props,通过子组件标签上的 v-slot 指令,直接接收到了一个插槽 props 对象:

        <my-component v-slot="data">{{data.text}}{{data.count}}</my-component>

子组件传入插槽的 props 作为了 v-slot 指令的值,可以在插槽内的表达式中访问。
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

具名作用域插槽的工作方式也是类似的,插槽 props 可以作为 v-slot 指令的值被访问到:v-slot:name=“data”。当使用缩写时是这样:

        <one-component><template #header="data">{{data}}</template><template #default="data">{{data}}</template><template #footer="data">{{data}}</template></one-component>

向具名插槽中传入 props:

                    template: `<div><header><slot name='header' :msg='"早上好"' v-bind:uname='"张三"''></slot></header><main><slot :msg='"中午好"' v-bind:uname='"李四"'></slot></main><footer><slot name='footer' v-bind:msg='"晚上好"' :uname='"王五"'></slot></footer></div>`

同时使用了具名插槽与默认插槽,则需要为默认插槽使用显式的 <template> 标签。尝试直接为组件添加 v-slot 指令将导致编译错误。这是为了避免因默认插槽的 props 的作用域而困惑:

        <!-- 该模板无法编译 --><one-component><template #header="data">{{ data }}</template><p v-slot="data">{{ data }}</p><template #footer="data">{{ data }}</template></one-component>

组件化案例-购物车

略,具体见代码实现:

<body><div class="main" id="app"><h2>组件化案例-购物车</h2><div class="container"><my-cart></my-cart></div></div><script src="../js/vue.js"></script><script>Vue.component('MyCart', {data: function() {return {title: '我的商品',list: [{id: 1,name: 'TCL彩电',price: 100,num: 1,img: 'img/a.jpg'},{id: 2,name: '机顶盒',price: 200,num: 1,img: 'img/b.jpg'},{id: 3,name: '海尔冰箱',price: 300,num: 1,img: 'img/c.jpg'},{id: 4,name: '小米手机',price: 400,num: 1,img: 'img/d.jpg'},{id: 5,name: 'PPTV电视',price: 500,num: 2,img: 'img/e.jpg'}]}},template: `<div class="cart"><cart-title :title='title'></cart-title><cart-list :list='list' @cart-del='deleteCart' @cart-change='changCartNum'></cart-list><cart-total :list='list'></cart-total></div>`,methods: {deleteCart: function(i) {this.list.splice(i, 1);},changCartNum: function(i, t, v) {let item = this.list[i];if (t === 'sub') {if (item.num <= 0) return;item.num--;} else if (t === 'add') {item.num++;} else {item.num = v;}}},components: {'CartTitle': {props: ['title'],template: `<div class="title" v-text='title'></div>`},'CartList': {props: ['list'],template: `<div><div class="item" :key="v.id" v-for="(v, i) in list"><img :src="'../' + v.img" alt=""><div class="name" v-text="v.name"></div><div class="change"><a href="javascritp:;" @click.prevent='$emit("cart-change", i, "sub")'>-</a><input type="text" class="num" :value='v.num' @blur='$emit("cart-change", i, "change", $event.target.value)'><a href="javascritp:;" @click.prevent='$emit("cart-change", i, "add")'>+</a></div><div class="del" @click='$emit("cart-del", i)'>×</div></div></div>`},'CartTotal': {props: ['list'],template: `<div class="total"><span v-text='"总价:" + totalAmount'></span><button>结算</button></div>`,computed: {totalAmount: function() {let amount = 0;for (let index = 0; index < this.list.length; index++) {const element = this.list[index];amount += element.price * element.num;}return amount;}}},}});let vm = new Vue({el: '#app',data: {}});</script>
</body>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/753324.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在AI创业热潮下,如何抓住AI赚钱机会,实现人生逆袭

随着人工智能技术的迅猛发展,AI创业热潮正席卷全球。这不仅为科技领域的专业人士提供了无限的商机,也为普通人开辟了全新的赚钱途径。本文将为您揭示在AI创业热潮下,普通人如何抓住AI赚钱机会,实现人生逆袭,同时探讨哪些行业适合应用AI技术。 一、普通人如何抓住AI赚钱机…

前端基础篇-快速了解 Vue 前端框架(Vue 指令)

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Vue 概述 2.0 Vue 指令 2.1 指令 - v-bind 2.2 指令 - v-model 2.3 指令 - v-on 2.4 指令 - v-if、v-else-if、v-else 2.5 指令 - v-show 2.6 指令 - v-for 3.0 生…

实现C++自定义的String类

一、简介 采用了COW写时复制的方式实现&#xff0c;即在每个String类数据域之前用了4个字节的空间进行引用计数。通过拷贝构造函数或者赋值运算符函数进行赋值时不会重新开辟空间&#xff0c;只会对引用计数加一&#xff0c;当有修改操作时&#xff0c;才会重新开辟新的空间&a…

es文档操作命令

文档操作 documents 创建数据&#xff08;put&#xff09; 向 user 索引下创建3条数据 PUT /user/_doc/1 {"name":"zhangsan","age":18,"sex":"男","info":"一顿操作猛如虎&#xff0c;一看工资2500"…

码云简化版使用教程

码云简化版使用教程 ①创建本地项目 ②在本地项目根目录下创建git相关目录及文件 ③在码云上创建新的仓库 ④在本地项目中配置仓库地址&#xff0c;提交项目内容 下面直接从第二步开始讲解 在本地项目根目录下创建git相关目录及文件 1、打开项目根目录&#xff0c;进入cmd界…

Linux应用 线程同步之互斥锁

1、概念 1.1 定义 互斥锁&#xff08;Mutex&#xff09;&#xff0c;又称互斥型信号量&#xff0c;是一种特殊的二值性信号量&#xff0c;主要用于实现对共享资源的独占式处理。任意时刻&#xff0c;互斥锁的状态只有两种&#xff1a;开锁或闭锁。当有任务持有时&#xff0c;…

旧衣服回收小程序开发,“互联网+”模式下巨大收益

近年来&#xff0c;在人们生活水平的提高下&#xff0c;旧衣物随之增加&#xff0c;如何处理旧衣服成为了当下大众所困扰的问题。 当下&#xff0c;旧衣回收行业已经成为了一个新的热门行业&#xff0c;我国人口众多&#xff0c;旧衣物的市场规模也在不断扩大&#xff0c;市场…

【QT入门】qmake和cmake的简单区别

声明&#xff1a;该专栏为本人学习Qt知识点时候的笔记汇总&#xff0c;希望能给初学的朋友们一点帮助(加油&#xff01;) 往期回顾&#xff1a; 【QT入门】Windows平台下 QT的编译过程-CSDN博客 【QT入门】VS2019QT的开发环境配置-CSDN博客 【QT入门】VS2019和QT Creator如何添…

基于springboot+vue的房屋交易平台

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

代码随想录算法训练营Day48 | LeetCode121. 买卖股票的最佳时机、LeetCode122.买卖股票的最佳时机II

LeetCode121. 买卖股票的最佳时机 动规五部曲&#xff1a; 1、dp[i][0]:在第i天持有股票的最大收入&#xff1b;dp[i][1]:在第i天不持有股票的最大收入。 2、递推公式&#xff1a;第i天持有股票&#xff0c;有两种情况&#xff1a;前一天已经持有&#xff0c;当天刚买入&#…

Greetings

Problem - 1915F - Codeforces 题意 给一些(l,r)找到所有能够包含(l,r)的数目 引入 也就是找逆序对个数 要用到归并排序中的思想&#xff1a; //https://www.luogu.com.cn/problem/P1216 #include<iostream> #include<cstdio> #include<stack> #include…

用python如何实现智能合约?如何使用remix编写solidity智能合约并部署上链

目录 用python如何实现智能合约? 直接展示下成功界面 下面分步骤说: remix代码 python链接remix代码

将查询出来数据中相对应的字段根据枚举类更改为其中文内容

&#x1f413;1.通过mapper.xml文件中的内容使用casewhen进行更换字段内容 SELECT case user_type when 101000 then 李明 when 101001 then 王丽 when 101002 then 王小黑 when 101003 then 王大黑 when 101004 then 超级大王 when 101005 then 小董 else end as 别称 from…

python面向对像之第二次笔记

python面向对像 一、面向对象的三大特性面向对象包含3大主要特性&#xff1a;封装私有成员继承复写 pass关键字多态 总结 一、面向对象的三大特性 面向对象包含3大主要特性&#xff1a; 封装 封装是面向对象编程中的一个重要概念&#xff0c;它指的是将数据&#xff08;属性&a…

STM32信息安全 1.2 课程架构介绍:芯片生命周期管理与安全调试

STM32信息安全 1.2 课程架构介绍&#xff1a;STM32H5 芯片生命周期管理与安全调试 下面开始学习课程的第二节&#xff0c;简单介绍下STM32H5芯片的生命周期和安全调试&#xff0c;具体课程大家可以观看STM32官方录制的课程&#xff0c;链接&#xff1a;1.2. 课程架构介绍&…

记一些有关Element Plus的样式修改

先记一个放着&#xff0c;后续慢慢补充。。。 一个 Vue 3 UI 框架 | Element Plus Radio 单选框 1、去除radio的圆圈 .box-radio {/deep/ .el-radio__input {display: none;} }

Leetcode 3085. Minimum Deletions to Make String K-Special

Leetcode 3085. Minimum Deletions to Make String K-Special 1. 解题思路2. 代码实现 题目链接&#xff1a;3085. Minimum Deletions to Make String K-Special 1. 解题思路 这一题思路上来说的话我们只需要统计一下word当中所有的字符出现的频次&#xff0c;然后依次排序&…

【QT入门】VS2019和QT Creator如何添加第三方模块

声明&#xff1a;该专栏为本人学习Qt知识点时候的笔记汇总&#xff0c;希望能给初学的朋友们一点帮助(加油&#xff01;) 往期回顾&#xff1a; 【QT入门】什么是qt&#xff0c;发展历史&#xff0c;特征&#xff0c;应用&#xff0c;QtCreator-CSDN博客 【QT入门】Windows平台…

模方信创版正式上线!支持水面一键修复、道路置平、纹理编辑...

现在国家大力推进信创国产化软硬件替代的政策背景下&#xff0c;大势智慧重磅发布模方信创版&#xff0c;以满足用户对在信创环境下进行实景三维模型修饰与编辑的需求。 模方信创版与重建大师信创版、DasViewer信创版一道&#xff0c;构筑起三维重建信创生态的“铁三角”&…

Unity PS5开发 天坑篇 之 DEVKit环境部署与系统升级02

上一篇各位大神们已经收到了SONY官方免费寄送的PS5开发机与测试机&#xff0c;恭喜大家成为SONY的开发者, 本篇继续PS5开发机的部署与开发套件使用。 一, PC安装PS5 SDK与系统升级 1. PC/PS5 SDK Manager下载安装包 登录开发者账号后&#xff0c;Development->Resources&a…