Vue组件_组件通信_todo案例

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
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值