01-组件-4步曲
案例用less写的样式, 所以下载
yarn add less less-loader@5.0.0 -D
模板标签
<template>
<div id="app">
<h3>案例:折叠面板</h3>
<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>
</div>
</template>
<script>
export default {
data() {
return {
isShow: false
}
}
}
</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;
}
.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>
在componnents里新建Panel
/目标: 如何创建和使用组件
1. 创建组件 -> 封装标签, 样式, js -> vue实例(脚手架环境, 我们采用.vue文件形式)
2. 引入组件
import Panel from "./components/Panel";
3. 注册组件 - 方法1(全局注册)
// 语法: Vue.component('组件名', 组件对象)
3. 注册组件 - 方式2(局部注册)
// 组件名: 组件对象
Panel.vue
<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
<template>
<div id="app">
<h3>案例:折叠面板</h3>
<Pannel></Pannel>
<Pannel></Pannel>
<Pannel></Pannel>
</div>
</template>
<script>
// 目标: 如何创建和使用组件
// 1. 创建组件 -> 封装标签, 样式, js -> vue实例(脚手架环境, 我们采用.vue文件形式)
// 2. 引入组件
import Panel from "./components/Panel";
// 3. 注册组件 - 方法1(全局注册)
// 语法: Vue.component('组件名', 组件对象)
// import Vue from 'vue'
// Vue.commponent('Pannel', Panel)
export default {
// 3. 注册组件 - 方式2(局部注册)
components: {
// 组件名: 组件对象
Pannel: Panel,
// Panel: Panel
// 组件名(key) 和 组件对象(value) 名字相同简写
// Panel
},
};
</script>
<style lang="less" scoped>
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>
图片显示
02-组件通信-父向子的基础使用
在componnents里新建MyProduct
App.vue
<template>
<div>
<MyProduct title="超级好吃的口水鸡" price="50" intro="开业大酬宾, 全场8折"></MyProduct>
<MyProduct title="超级好吃的铁锅炖" price="300" intro="正宗的东北铁锅炖,嘎嘎好吃"></MyProduct>
<MyProduct title="超级好吃的蛙锅" price="500" intro="好吃的停不下来,都来尝一尝吧"></MyProduct>
</div>
</template>
<script>
// 目标: 组件通信
// 场景(口诀): 从某.vue文件, 向另外.vue文件 传值
// 使用:
// 方法1: 父 -> 子(传值)
// 被引入的是儿子
// 语法:
// (1): 子组件内, props:[变量1, 变量2]
// (2): 父组件内, 在使用组件标签时, 向变量传值
import MyProduct from "./components/MyProduct";
export default {
components: {
MyProduct,
},
};
</script>
<style>
</style>
MyProduct.vue
<template>
<div class="my-product">
<h3>标题: {
{ title }}</h3>
<p>价格: {
{ price }}</p>
<p>{
{ intro }}</p>
</div>
</template>
<script>
export default {
// (1): 子组件内定义变量
// vue会把他们解析成变量的
props: ["title", "price", "intro"],
};
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
组件通信-父向子-配合循环
App.vue
<template>
<div>
<MyProduct
v-for="obj in list"
:key="obj.id"
:title="obj.proname"
:price="obj.proprice"
:intro="obj.info"
></MyProduct>
</div>
</template>
<script>
// 目标: 组件配合循环使用
// v-for 每次循环是独立, 组件每创建一次独立
// 组件一般就用于展示数据的
import MyProduct from "./components/MyProduct";
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,
},
};
</script>
<style>
</style>
MyProduct.vue
<template>
<div class="my-product">
<h3>标题: {
{ title }}</h3>
<p>价格: {
{ price }}</p>
<p>{
{ intro }}</p>
</div>
</template>
<script>
export default {
// (1): 子组件内定义变量
// vue会把他们解析成变量的
props: ["title", "price", "intro"],
};
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
组件通信-子向父
在componnents里新建MyProduct_Sub
App.vue
<template>
<div>
<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";
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: "炎热的夏天, 来个冰激凌了",
},
],
};
},
methods: {
fn(ind, price) {
// 数据源list里砍价
let obj = this.list[ind];
if (obj.proprice > 1) {
// obj.proprice = (obj.proprice - price).toFixed(2)
obj.proprice -= price;
}
},
},
components: {
MyProduct,
},
};
</script>
<style>
</style>
MyProduct_Sub
<template>
<div class="my-product">
<h3>标题: {
{ title }}</h3>
<p>价格: {
{ price }}</p>
<p>{
{ intro }}</p>
<button @click="kanFn">砍一刀</button>
</div>
</template>
<script>
// 目标: 砍一刀
// 结论: props的变量(只读的)
// 原因: 修改props变量值的时候,出现红色警告
// 我在子组件改props值也没用, 父组件重新渲染会把props的值覆盖
// 目标: 子向父传值
// 语法:
// (1): 父组件内, 给子组件标签 - 绑定自定事件
// @自定义事件名="父methods里函数名"
// (2): 子组件内, "恰当的时机"
// this.$emit('自定义事件名', 值)
// 效果: 触发此标签身上的对应事件名
export default {
// (1): 子组件内定义变量
// vue会把他们解析成变量的
props: ["title", "price", "intro", "index"],
methods: {
kanFn() {
// 把索引和砍得价格传给父组件
this.$emit("subPrice", this.index, Math.random());
},
},
};
</script>
<style>
.my-product {
width: 400px;
padding: 20px;
border: 2px solid #000;
border-radius: 5px;
margin: 10px;
}
</style>
画图显示
todo案例
1.todo案例-创建工程和组件
vue create todo-list // 建工程
根据需求定义3个组件准备复用
components/TodoHeader.vue - 复制标签和类名
<template>
<header class="header">
<h1>todos</h1>
<input id="toggle-all" class="toggle-all" type="checkbox" >
<label for="toggle-all"></label>
<input
class="new-todo"
placeholder="输入任务名称-回车确认"
autofocus
/>
</header>
</template>
<script>
export default {
}
</script>
components/TodoMain.vue - 复制标签和类名
<template>
<ul class="todo-list">
<!-- completed: 完成的类名 -->
<li class="completed" >
<div class="view">
<input class="toggle" type="checkbox" />
<label>任务名</label>
<button class="destroy"></button>
</div>
</li>
</ul>
</template>
<script>
export default {
}
</script>
components/TodoFooter.vue - 复制标签和类名
<template>
<footer class="footer">
<span class="todo-count">剩余<strong>数量值</strong></span>
<ul class="filters">
<li>
<a class="selected" href="javascript:;" >全部</a>
</li>
<li>
<a href="javascript:;">未完成</a>
</li>
<li>
<a href="javascript:;" >已完成</a>
</li>
</ul>
<button class="clear-completed" >清除已完成</b