Vue.js------Vue组件基础

ops/2024/10/18 9:19:58/
  1. 能够理解Vue组件概念和作用
  2. 能够掌握封装创建组件能力
  3. 能够使用组件之间通信
  4. 能够完成todo案例

一.Vue组件创建和使用

1.折叠面板-实现多个 

 

创建一个文件夹demo 具体步骤请参考vue.js---vue基础

⚫ 解决方案: 采用vue提供的单.vue文件-组件方式来封装一套然后复用

在components文件夹下创建组件PanelComponent.vue

javascript"><template><div><div class="title"><h4>芙蓉楼送辛渐</h4><span class="btn" @click="isShow = !isShow">{{ isShow ? "收起" : "展开" }}</span></div><div class="container" v-show="isShow"><p>寒雨连江夜入吴,</p><p>平明送客楚山孤。</p><p>洛阳亲友如相问,</p><p>一片冰心在玉壶。</p></div></div>
</template><script>
export default {data() {return {isShow: false,};},
};
</script><style scoped>
.title {display: flex;justify-content: space-between;align-items: center;border: 1px solid #ccc;padding: 0 1em;
}.title h4 {line-height: 2;margin: 0;
}.container {border: 1px solid #ccc;padding: 0 1em;
}.btn {/* 鼠标改成手的形状 */cursor: pointer;
}</style>

 App.vue

javascript"><template><div id="app"><h3>案例:折叠面板</h3><Pannel></Pannel><Pannel></Pannel><Pannel></Pannel></div>
</template><script>
import Pannel from './components/PanelComponent.vue'
export default {components: {Pannel: Pannel}
}
</script><style lang="less">
body {background-color: #ccc;#app {width: 400px;margin: 20px auto;background-color: #fff;border: 4px solid blueviolet;border-radius: 1em;box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);padding: 1em 2em 2em;h3 {text-align: center;}}
}
</style>

下载less,less-loader第三方库

npm install less-loader --save-dev

启动服务器,打开网站

 

1. 遇到重复标签想复用?

      封装成组件

2. 组件好处?   各自独立, 便于复用

2.组件概念

  • 组件是可复用的 Vue 实例, 封装标签, 样式和JS代码
  • 组件化 :封装的思想,把页面上 `可重用的部分` 封装为 `组件`,从而方便项目的 开发 和 维护
  • 一个页面, 可以拆分成一个个组件,一个组件就是一个整体, 每个组件可以有自己独立的 结构 样式 和 行为(html, css和js)

组件是什么? 可复用的vue实例, 封装标签, 样式, JS

什么时候封装组件? 遇到重复标签, 可复用的时候

组件好处? 各自独立, 互不影响

 3.组件_基础使用

目标:每个组件都是一个独立的个体, 代码里体现为一个独立的.vue文件

创建组件, 封装要复用的标签, 样式, JS代码

2. 注册组件

  • 全局注册 – main.js中 – 语法如图

  • 局部注册 – 某.vue文件内 – 语法如图

3. 使用组件

 

 文件demo\src\components\PanelComponent_1.vue

javascript"><template><div><div class="title"><h4>芙蓉楼送辛渐</h4><span class="btn" @click="isShow = !isShow">{{ isShow ? "收起" : "展开" }}</span></div><div class="container" v-show="isShow"><p>寒雨连江夜入吴,</p><p>平明送客楚山孤。</p><p>洛阳亲友如相问,</p><p>一片冰心在玉壶。</p></div></div>
</template><script>
export default {data() {return {isShow: true,};},
};
</script><style scoped>
.title {display: flex;justify-content: space-between;align-items: center;border: 1px solid #ccc;padding: 0 1em;
}
.title h4 {line-height: 2;margin: 0;
}
.container {border: 1px solid #ccc;padding: 0 1em;
}
.btn {/* 鼠标改成手的形状 */cursor: pointer;
}
</style>

 App.vue

javascript"><template><div id="app"><h3>案例:折叠面板</h3><!-- 4. 组件名当做标签使用 --><!-- <组件名></组件名> --><PannelG></PannelG><PannelL></PannelL></div>
</template><script>
// 目标: 局部注册 (用的多)
// 1. 创建组件 - 文件名.vue
// 2. 引入组件
import Pannel from './components/PanelComponent_1.vue'
export default {// 3. 局部 - 注册组件/*语法: components: {"组件名": 组件对象}*/components: {PannelL: Pannel}
}
</script><style lang="less">
body {background-color: #ccc;#app {width: 400px;margin: 20px auto;background-color: #fff;border: 4px solid blueviolet;border-radius: 1em;box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);padding: 1em 2em 2em;h3 {text-align: center;}}
}
</style>

main.js

javascript">import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = false// 目标: 全局注册 (一处定义到处使用)
// 1. 创建组件 - 文件名.vue
// 2. 引入组件
import Pannel from './components/PanelComponent_1.vue'
// 3. 全局 - 注册组件
/*语法: Vue.component("组件名", 组件对象)
*/
Vue.component("PannelG", Pannel)new Vue({render: h => h(App),
}).$mount('#app')

 

创建和使用组件步骤?

      创建.vue文件 – 标签 – 样式 – JS进去

      注册组件 (全局 / 局部)

      使用组件 (组件名用作标签)

组件运行结果? 把组件标签最终替换成, 封装的组件内标签

4.组件-scoped作用 

  • 准备: 当前组件内标签都被添加 data-v-hash值 的属性
  • 获取: css选择器都被添加 [data-v-hash值] 的属性选择器

Vue组件内样式, 只针对当前组件内标签生效如何做? 给style上添加scoped

原理和过程是什么? 会自动给标签添加data-v-hash值属性, 所有选择都带属性选择

 二.Vue组件通信

1.组件通信_父传子_props 

目标:父组件 -> 子组件 传值

首先明确父和子是谁, 在父引入子 (被引入的是子)

  • 父: App.vue
  • 子: MyProduct.vue

创建MyProduct.vue如下图所示

子组件内, 定义变量, 准备接收, 然后使用变量

2. 父组件(App.vue)内, 要展示封装的子组件(MyProduct.vue)引入组件, 注册组件, 使用组件, 传值进去

App.vue

javascript"><template><div><!-- 目标: 父(App.vue) -> 子(MyProduct.vue) 分别传值进入需求: 每次组件显示不同的数据信息步骤(口诀):1. 子组件 - props - 变量 (准备接收)2. 父组件 - 传值进去--><Product title="好吃的口水鸡" price="50" intro="开业大酬宾, 全场8折"></Product><Product title="好可爱的可爱多" price="20" intro="老板不在家, 全场1折"></Product><Product title="好贵的北京烤鸭" price="290" :intro="str"></Product></div>
</template><script>
// 1. 创建组件 (.vue文件)
// 2. 引入组件
import Product from './components/MyProduct'
export default {data() {return {str: "好贵啊, 快来啊, 好吃"}},// 3. 注册组件components: {// Product: Product // key和value变量名同名 - 简写Product}
}
</script><style></style>

demo\src\components\MyProduct.vue

javascript"><template><div class="my-product"><h3>标题: {{ title }}</h3><p>价格: {{ price }}元</p><p>{{ intro }}</p></div>
</template><script>
export default {props: ['title', 'price', 'intro']
}
</script><style>
.my-product {width: 400px;padding: 20px;border: 2px solid #000;border-radius: 5px;margin: 10px;
}
</style>

什么时候需要父传子技术? 从一个vue组件里把值传给另一个vue组件(父->子)

父传子口诀(步骤)是什么?

子组件内, props定义变量, 在子组件使用变量

父组件内, 使用子组件, 属性方式给props变量传值

 2.组件通信_父向子-配合循环

目标:父组件 -> 子组件 循环使用-传值

每次循环obj和组件都是独立的, 新的

App.vue

javascript"><template><div><MyProduct v-for="obj in list" :key="obj.id" :title="obj.proname" :price="obj.proprice" :intro="obj.info"></MyProduct></div>
</template><script>
// 目标: 循环使用组件-分别传入数据
// 1. 创建组件
// 2. 引入组件
import MyProduct from './components/MyProduct.vue'
export default {data() {return {list: [{id: 1,proname: "超级好吃的棒棒糖",proprice: 18.8,info: "开业大酬宾, 全场8折",},{id: 2,proname: "超级好吃的大鸡腿",proprice: 34.2,info: "好吃不腻, 快来买啊",},{id: 3,proname: "超级无敌的冰激凌",proprice: 14.2,info: "炎热的夏天, 来个冰激凌了",},],};},// 3. 注册组件components: {// MyProduct: MyProductMyProduct}
};
</script><style></style>

 demo\src\components\MyProduct.vue

javascript"><template><div class="my-product"><h3>标题: {{ title }}</h3><p>价格: {{ price }}元</p><p>{{ intro }}</p></div>
</template><script>
export default {props: ['title', 'price', 'intro']
}
</script><style>
.my-product {width: 400px;padding: 20px;border: 2px solid #000;border-radius: 5px;margin: 10px;
}
</style>

循环使用组件注意事项? 每次循环, 变量和组件, 都是独立的 

3.单向数据流  

目标:从父到子的数据流向, 叫单向数据流

原因: 子组件修改, 不通知父级, 造成数据不一致性

Vue规定props里的变量, 本身是只读的

为何不建议, 子组件修改父组件传过来的值?

父子数据不一致, 而且子组件是依赖父传入的值

什么是单向数据流? 从父到子的数据流向, 叫单向数据流

props里定义的变量能修改吗?不能, props里的变量本身是只读的 

4.组件通信_子向父_自定义事件 

目标:子组件触发父自定义事件方法

  • 需求: 商品组件, 实现砍价功能

  • 前置补充, 父 -> 索引 -> 子组件 (用于区分哪个子组件)

父组件内, 绑定自定义事件和事件处理函数

语法: @自定义事件名="父methods里函数名"

子组件内, 恰当的时机, 触发父给我绑的自定义事件, 导致父methods里事件处理函数执行  

 App.vue

javascript"><template><div><!-- 目标: 子传父 --><!-- 1. 父组件, @自定义事件名="父methods函数" --><MyProduct v-for="(obj, ind) in list" :key="obj.id" :title="obj.proname" :price="obj.proprice" :intro="obj.info":index="ind" @subprice="fn"></MyProduct></div>
</template><script>
import MyProduct from './components/MyProduct_sub.vue'
export default {data() {return {list: [{id: 1,proname: "超级好吃的棒棒糖",proprice: 18.8,info: "开业大酬宾, 全场8折",},{id: 2,proname: "超级好吃的大鸡腿",proprice: 34.2,info: "好吃不腻, 快来买啊",},{id: 3,proname: "超级无敌的冰激凌",proprice: 14.2,info: "炎热的夏天, 来个冰激凌了",},],};},components: {MyProduct},methods: {fn(inde, price) {// 逻辑代码this.list[inde].proprice > 1 && (this.list[inde].proprice = (this.list[inde].proprice - price).toFixed(2))}}
};
</script><style></style>

demo\src\components\MyProduct_sub.vue

javascript"><template><div class="my-product"><h3>标题: {{ title }}</h3><p>价格: {{ price }}元</p><p>{{ intro }}</p><button @click="subFn">宝刀-砍1元</button></div>
</template><script>
import eventBus from '../EventBus'
export default {props: ['index', 'title', 'price', 'intro'],methods: {subFn() {this.$emit('subprice', this.index, 1) // 子向父eventBus.$emit("send", this.index, 1) // 跨组件}}
}
</script><style>
.my-product {width: 400px;padding: 20px;border: 2px solid #000;border-radius: 5px;margin: 10px;
}
</style>

javascript">import Vue from 'vue'
// 导出空白vue对象
export default new Vue()

 

什么时候使用子传父技术?

当子想要去改变父里的数据

子传父如何实现? 父组件内, 给组件@自定义事件="父methods函数" 子组件内, 恰当时机this.$emit('自定义事件名', 值)

总结:

组件是什么?

是一个vue实例, 封装标签, 样式和JS代码

组件好处? 便于复用, 易于扩展

组件通信哪几种, 具体如何实现? 父 -> 子 父

5.组件通信-EventBus  

目标:App.vue里引入MyProduct.vue和List.vue

目标:常用于跨组件通信时使用

⚫ 语法

  • src/EventBus/index.js – 创建空白Vue对象并导出
  • 在要接收值的组件(List.vue) eventBus.$on('事件名', 函数体)
  • 要传递值的组件(MyProduct.vue) eventBus.$emit('事件名', 值)

App.vue 

javascript"><template><div style="overflow: hidden;"><div style="float: left;"><MyProductv-for="(obj, ind) in list":key="obj.id":title="obj.proname":price="obj.proprice":intro="obj.info":index="ind"@subprice="fn"></MyProduct></div><div style="float: left;"><List :arr="list"></List></div></div>
</template><script>
import MyProduct from "./components/MyProduct_sub.vue";
import List from "./components/ProductList.vue";
export default {data() {return {list: [{id: 1,proname: "超级好吃的棒棒糖",proprice: 18.8,info: "开业大酬宾, 全场8折",},{id: 2,proname: "超级好吃的大鸡腿",proprice: 34.2,info: "好吃不腻, 快来买啊",},{id: 3,proname: "超级无敌的冰激凌",proprice: 14.2,info: "炎热的夏天, 来个冰激凌了",},],};},components: {MyProduct,List,},methods: {fn(inde, price) {this.list[inde].proprice > 1 &&(this.list[inde].proprice = (this.list[inde].proprice - price).toFixed(2));},},
};
</script><style>
</style>

 components/ProductList.vue

javascript"><template><ul class="my-product"><li v-for="(item, index) in productList" :key="index"><span>{{ item.proname }}</span><span>{{ item.proprice }}</span></li></ul>
</template><script>
import eventBus from "../EventBus/index";export default {props: ["arr"],data() {return {productList: []};},created() {this.productList = [...this.arr]; // 创建副本eventBus.$on("send", (index, price) => {this.handlePriceUpdate(index, price);});},methods: {handlePriceUpdate(index, price) {if (this.productList[index].proprice > 1) {// 更新副本而不是原始的 arrthis.productList[index].proprice = (this.productList[index].proprice - price).toFixed(2);// 发送事件通知父组件更新eventBus.$emit("priceUpdated", this.productList);}}}
};
</script><style>
.my-product {width: 400px;padding: 20px;border: 2px solid #000;border-radius: 5px;margin: 10px;
}
</style>

 components/MyProduct_sub.vue

javascript"><template><div class="my-product"><h3>标题: {{ title }}</h3><p>价格: {{ price }}元</p><p>{{ intro }}</p><button @click="subFn">宝刀-砍1元</button></div>
</template><script>
import eventBus from '../EventBus'
export default {props: ['index', 'title', 'price', 'intro'],methods: {subFn() {this.$emit('subprice', this.index, 1) // 子向父eventBus.$emit("send", this.index, 1) // 跨组件}}
}
</script><style>
.my-product {width: 400px;padding: 20px;border: 2px solid #000;border-radius: 5px;margin: 10px;
}
</style>

 

什么时候使用eventBus技术? 当2个没有引用关系的组件之间要通信传值

eventBus技术本质是什么? 空白Vue对象, 只负责$on和$emit


http://www.ppmy.cn/ops/5371.html

相关文章

皇后之战:揭秘N皇后问题的多维解法与智慧【python 力扣52题】

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

Ollama教程——使用langchain:ollama与langchain的强强联合

相关文章: Ollama教程——入门&#xff1a;开启本地大型语言模型开发之旅 Ollama教程——模型&#xff1a;如何将模型高效导入到ollama框架 Ollama教程——兼容OpenAI API&#xff1a;高效利用兼容OpenAI的API进行AI项目开发 Ollama教程——使用langchain&#xff1a;ollama与…

快速删除node_modules依赖包的命令rimraf

1、安装rimraf npm install -g rimraf 2、使用命令删除node_modules rimraf node_modules *** window系统&#xff0c;使用命令很快就删除node_modules ***

第二十六章: mybatis plus 如何使用`LambdaQueryWrapper` 和 `QueryWrapper`

第二十六章&#xff1a; mybatis plus 如何使用LambdaQueryWrapper 和 QueryWrapper 目标 掌握 LambdaQueryWrapper 和 QueryWrapper的用法掌握 List对象转map对象掌握 List对象获取某字段的集合 LambdaQueryWrapper 和 QueryWrapper 是 MyBatis-Plus 中提供的查询条件构造器…

笔记本电脑上的聊天机器人: 在英特尔 Meteor Lake 上运行 Phi-2

对应于其强大的能力&#xff0c;大语言模型 (LLM) 需要强大的算力支撑&#xff0c;而个人计算机上很难满足这一需求。因此&#xff0c;我们别无选择&#xff0c;只能将它们部署至由本地或云端托管的性能强大的定制 AI 服务器上。 为何需要将 LLM 推理本地化 如果我们可以在典配…

【干货精品分享】Elasticsearch 6.7 Should 子语句的失效

在ES 使用多条件 查询&#xff0c;并且是多个条件只需要满足部分条件的时候&#xff0c;我们通常会使用到ES的should查询 GET /trademark_query_index/_search {"query":{"bool" : {"must":[{"match" : {"origin": {"…

Redis 核心知识点常考面试题(持续更新中)

Redis 核心知识点常考面试题&#xff08;持续更新中&#xff09; Redis单线程IO多路复用原理Redis缓存穿透、缓存雪崩、缓存击穿问题Redis与数据库双写不一致问题基于Redis实现分布式锁的的应用场景Redis持久化方式Redis内存淘汰机制Redis删除策略Redis主从复制、哨兵、集群Red…

TCP/IP_第八章_静态路由_实验案例一

实验案例一&#xff1a;配置静态路由实现全网互通 1、实验环境 如图8.10所示&#xff0c;三台路由器R1&#xff0e;R2&#xff0c;R3两两互连&#xff0c;每台路由器上都配置了Loopback地址模拟网络环境。 2、需求描述 需要在三台路由器上配置静态路由&#xff0c;以实现各网…