【前端Vue】Vue从0基础完整教程第4篇:面经PC端 - Element (下)【附代码文档】

news2024/11/25 16:51:02

Vue从0基础到大神学习完整教程完整教程(附代码资料)主要内容讲述:vue基本概念,vue-cli的使用,vue的插值表达式,{{ gaga }},{{ if (obj.age > 18 ) { } }},vue指令,综合案例 - 文章标题编辑vue介绍,开发vue的方式,基本使用,如何覆盖webpack配置,目录分析与清理,vue单文件组件的说明,vue通过data提供数据,通过插值表达式显示数据,安装vue开发者工具,v-bind指令,v-on指令,v-if 和 v-show,v-model,v-text 和 v-html。day-08vuex介绍,语法,模块化,小结。面经PC端-element (上)初始化,request,router,login模块,layout模块,dashboard模块(了解)。面经PC端 - Element (下)Article / list 列表,Article / add 添加,Article / del 删除,Article / upd 修改,Article / preview 预览,yarn-补充。vue指令(下),成绩案例,计算属性,属性监听v-for,样式处理,基本结构与样式,基本渲染,删除,新增,处理日期格式,基本使用,计算属性的缓存的问题,成绩案例-计算属性处理总分 和 平均分,计算属性的完整写法,大小选,基本使用,复杂类型的监听-监听的完整写法,成绩案例-监听数据进行缓存,配置步骤 (两步),使用演示。vue指令(下),成绩案例,计算属性,属性监听v-for,样式处理,基本结构与样式,基本渲染,删除,新增,处理日期格式,基本使用,计算属性的缓存的问题,成绩案例-计算属性处理总分 和 平均分,计算属性的完整写法,大小选,基本使用,复杂类型的监听-监听的完整写法,成绩案例-监听数据进行缓存,配置步骤 (两步),使用演示。组件化开发,组件通信,todo案例,作业什么是组件化开发,组件的注册,全局注册组件,组件的样式冲突 ,组件通信 - 父传子 props 传值,v-for 遍历展示组件练习,单向数据流,组件通信 - 子传父,props 校验,布局,任务组件todo,列表,删除,修改:不做了!下面代码其实就是我想让大家练习,添加,剩余数量,清空已完成,小选与大选,筛选:作业,本地存储,附加练习_1.喜欢小狗狗吗,附加练习_2.点击文字变色,附加练习_3. 循环展示狗狗,附加练习_4.选择喜欢的狗。v-model,ref 和 nextTick,dynamic 动态组件,自定义指令,插槽,案例:商品列表v-model 语法糖,v-model给组件使用,动态组件的基本使用,自定义指令说明,自定义指令 - 局部注册,自定义指令 - 全局注册,自定义指令 - 指令的值,默认插槽 slot,后备内容 (默认值),具名插槽,作用域插槽,案例概览,静态结构,MyTag 组件,MyTable 组件。生命周期,单页应用程序与路由,vue-router研究生命周期的意义,生命周期函数(钩子函数),组件生命周期分类,SPA - 单页应用程序,路由介绍,vue-router介绍,vue-router使用,配置路由规则,路由的封装,vue路由 - 声明式(a标签转跳)导航,vue路由 - 重定向和模式,vue路由 - 编程式(JS代码进行转跳)导航,综合练习 - 面经基础版,组件缓存 keep-alive。面经 H5 端 - Vant(上)初始化,vant,axios封装,router,主题定制-了解,登录&注册。面经 H5 端 - Vant(下)列表,详情,收藏 与 喜欢,我的(个人中心)。Day01_vuex今日学习目标(边讲边练),1.vuex介绍,2.vuex学习内容,3.vuex例子准备,vuex-store准备,5.vuex-state数据源,【vuex-mutations定义-同步修改,【vuex-mutations使用,8.vuex-actions定义-异步修改,9.vuex-actions使用,10.vuex-重构购物车-准备Store,11.vuex-重构购物车-配置项(上午结束),vuex-getters定义-计算属性,13.vuex-getters使用,14.vuex-modules定义-分模块,15.分模块-影响state取值方式,16.分模块-命名空间,扩展: 使用Devtools调试vuex数据。

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~


组件化开发

什么是组件化开发

组件化开发 指的是:根据封装的思想,把页面上 可重用的部分 封装为 组件,从而方便项目的 开发 和 维护。

一个页面, 可以拆分成一个个组件,一个组件就是一个整体, 每个组件可以有自己独立的 结构 样式 和 行为

例如: 所展示的效果,就契合了组件化开发的思想。

用户可以通过拖拽组件的方式,快速生成一个页面的布局结构。

前端组件化开发的好处主要体现在以下两方面:

  • 提高了前端代码的复用性和灵活性

  • 提升了开发效率和后期的可维护性

vue 是一个完全支持组件化开发的框架。vue 中规定组件的后缀名是 .vue

组件的注册

刚才我们创建使用的是 App.vue 根组件, 这个比较特殊, 是最大的一个根组件

而App.vue根组件内, 还可以写入一些小组件, 而这些组件, 要使用, 就需要先注册!

注册组件有两种注册方式: 分为“全局注册”和“局部注册”两种

  • 被全局注册的组件,可以在任意的组件模板范围中使用 通过Vue.component()
  • 被局部注册的组件,只能在当前注册的组件模板范围内使用 通过components

局部注册

  • 把独立的组件封装一个.vue文件中,推荐放到components文件夹
components
  -- HmHeader.vue
  -- HmContent.vue
  -- HmFooter.vue
  • 通过组件的components配置 局部注册组件
import HmHeader from './components/HmHeader'
import HmContent from './components/HmContent'
import HmFooter from './components/HmFooter'

export default {
  // data methods filters computed watch
  components: {
    // 组件名: 组件
    // 组件名:注意,不能和html内置的标签重名
    // 使用的时候:直接通过组件名去使用
    // HmHeader  HmHeader  hm-header
    HmHeader,
    HmContent,
    HmFooter
  }
}

==注意点:注册的组件的名字不能和HTML内置的标签重名==

  • 可以在模板中使用组件,,,,使用组件和使用html的标签是一样的,,,可以多次使用
<template>
  <div>
    <!-- 组件注册好了,就跟使用html标签一样了 -->
    <hm-header></hm-header>
    <hm-content></hm-content>
    <hm-footer></hm-footer>
  </div>
</template>

==局部注册的组件只能在当前组件中使用==

全局注册组件

  • components文件夹中创建一些新的组件
components
  -- HmHeader.vue
  -- HmContent.vue
  -- HmFooter.vue
  • main.js中通过Vue.component()全局注册组件
import HmHeader from './components/HmHeader'
import HmContent from './components/HmContent'
import HmFooter from './components/HmFooter'

// 全局注册
// Vue.component(名字, 组件)
Vue.component('HmHeader', HmHeader)
Vue.component('HmContent', HmContent)
Vue.component('HmFooter', HmFooter)
  • 使用
<template>
  <div>
    <!-- 组件注册好了,就跟使用html标签一样了 -->
    <hm-header></hm-header>
    <hm-content></hm-content>
    <hm-footer></hm-footer>
  </div>
</template>

==注意:全局注册的组件 可以在任意的组件中去使用==

组件名的大小写

在进行组件的注册时,定义组件名的方式有两种:

  • 注册使用短横线命名法,例如 hm-header 和 hm-main
  Vue.component('hm-button', HmButton)

使用时 <hm-button> </hm-button>

  • 注册使用大驼峰命名法,例如 HmHeader 和 HmMain
  Vue.component('HmButton', HmButton)

使用时 <HmButton> </HmButton><hm-button> </hm-button> 都可以

推荐定义组件名时, 用大驼峰命名法, 更加方便

全局注册

Vue.component('HmButton', HmButton)

局部注册:

components: {
  HmHeader,
  HmMain,
  HmFooter
}

使用时, 推荐遵循html5规范, 小写横杠隔开

<hm-header></hm-header>
<hm-main></hm-main>
<hm-footer></hm-footer>

通过 name 注册组件 (了解)

组件在开发者工具中显示的名字可以通过name进行修改

在注册组件期间,除了可以直接提供组件的注册名称之外,还可以把组件的 name 属性作为注册后组件的名称

组件内容:

<template>
  <button>按钮组件</button>
</template>

<script>
export default {
  name: 'HmButton'
}
</script>

<style lang="less">
button {
  width: 80px;
  height: 50px;
  border-radius: 5px;
  background-color: pink;
}
</style>

进行注册:

import HmButton from './components/hm-button.vue'
Vue.component(HmButton.name, HmButton)  // 等价于 app.component('HmButton', HmButton)

组件的样式冲突 scoped

默认情况下,写在组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。

组件样式默认会作用到全局, 就会影响到整个 index.html 中的 dom 元素

  • 全局样式: 默认组件中的样式会作用到全局
  • 局部样式: 可以给组件加上 scoped 属性, 可以让样式只作用于当前组件
<style lang="less" scoped>
div {
  background-color: pink;
}
</style>

原理:

  1. 添加scoped后, 会给当前组件中所有元素, 添加上一个自定义属性

image-20201219130504878

  1. 添加scoped后, 每个style样式, 也会加上对应的属性选择器

image-20201219130630023

最终效果: 必须是当前组件的元素, 才会有这个自定义属性, 才会被这个样式作用到

组件通信

每个组件都有自己的数据, 提供在data中, 每个组件的数据是独立的, 组件数据无法互相直接访问 (合理的)

但是如果需要跨组件访问数据, 就需要用到组件通信

组件通信的方式有很多: 现在先关注两种, 父传子 子传父

组件通信 - 父传子 props 传值

语法:

  1. 父组件通过给子组件加属性传值
<Son price="100" title="不错" :info="msg"></Son>
  1. 子组件中, 通过props属性接收
props: ['price', 'title', 'info']

需求: 封装一个商品组件 my-product

image-20201219140441042

my-product.vue

<template>
  <div class="my-product">
    <h3>标题: {{ title }}</h3>
    <p>价格: {{ price }}元</p>
    <p>{{ info }}</p>
  </div>
</template>

<script>
export default {
  props: ['title', 'price', 'info']
}
</script>

<style>
.my-product {
  width: 400px;
  padding: 20px;
  border: 2px solid #000;
  border-radius: 5px;
  margin: 10px;
}
</style>

v-for 遍历展示组件练习

需求: 遍历展示商品列表

假定, 发送请求回来的商品数据,

list: [
  { id: 1, proname: '超级好吃的棒棒糖', proprice: 18.8 },
  { id: 2, proname: '超级好吃的大鸡腿', proprice: 34.2 },
  { id: 3, proname: '超级无敌的冰激凌', proprice: 14.2 }
]

v-for 遍历展示

<template>
  <div class="container">
    <h3>我是app组件的内容</h3>
    <my-product 
      v-for="item in list" :key="item.id" 
      :price="item.proprice" 
      :title="item.proname" 
      :info="msg">
    </my-product>
  </div>
</template>

image-20201219141252468

单向数据流

/* 
  在vue中需要遵循单向数据流原则
  1. 父组件的数据发生了改变,子组件会自动跟着变
  2. 子组件不能直接修改父组件传递过来的props  props是只读的
*/

==如果父组件传给子组件的是一个对象,子组件修改对象的属性,是不会报错的,,,,也应该避免==

组件通信 - 子传父

需求: 砍价

image-20201220111611954

  1. 子组件可以通过 this.$emit('事件名', 参数1, 参数2, ...) 触发事件的同时传参的
   this.$emit('sayPrice', 2)
  1. 父组件给子组件注册一个自定义事件
   <my-product 
     ...
     @sayPrice="sayPrice">
   </my-product>

父组件并提供对应的函数接收参数

   methods: {
     sayPrice (num) {
       console.log(num)
     }
   },

props 校验

props 是父传子, 传递给子组件的数据, 为了提高 子组件被使用时 的稳定性, 可以进行props校验, 验证传递的数据是否符合要求

默认的数组形式, 不会进行校验, 如果希望校验, 需要提供对象形式的 props

风格指南:

props: {
    ...
}

props 提供了多种数据验证方案,例如:

  • 基础的类型检查 Number
  • 多个可能的类型 [String, Number]
  • 必填项校验 required: true
  • 默认值 default: 100
  • 自定义验证函数

官网语法: [地址](

{
  props: {
    // 基础的类型检查
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // -------------------------------------------------------------------------
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
}

todo案例

完整效果演示

品牌管理_铺增删

布局

1614086651742

  • App.vue
<template>
  <section class="todoapp">


    <!-- 头部:输入框 -->
    <header class="header">
      <h1>todos</h1>
      <input class="new-todo" placeholder="输入新计划" autofocus>
    </header>


    <!-- 列表: -->
    <section class="main">
      <input id="toggle-all" class="toggle-all" type="checkbox">
      <label for="toggle-all">Mark all as complete</label>
      <ul class="todo-list">

          <li class="completed">
              <div class="view">
                  <input class="toggle" type="checkbox" checked>
                  <label>吃饭</label>
                  <button class="destroy"></button>
              </div>
          </li>

      </ul>
    </section>


    <!-- 底部:状态栏 -->
    <footer class="footer">
      <span class="todo-count">剩余<strong>0</strong>未完成 </span>
      <ul class="filters">
        <li>
          <a class="selected" href="#/">全部</a>
        </li>
        <li>
          <a href="#/active">未完成</a>
        </li>
        <li>
          <a href="#/completed">已完成</a>
        </li>
      </ul>
      <button class="clear-completed">清除已完成</button>
    </footer>


  </section>
</template>
  • main.js中导入通用的样式 app.vue内部
import './styles/todos.css'

任务组件todo

  • 把任务内容单独拿出来进行封装 todo.vue
<template>
  <li class="completed">
      <div class="view">
          <input class="toggle" type="checkbox" checked>
          <label>吃饭</label>
          <button class="destroy"></button>
      </div>
  </li>
</template>

<script>
</script>

<style>
</style>
  • 导入app.vue组件,进行注册使用
import todo from './components/todo.vue';
export default {
  // 局部注册组件
  components: {
    todo
  },
}

列表

  • App.vue提供了任务列表数据
data () {
  return {
    list: [
      { id: 1, name: '吃饭', isDone: true },
      { id: 2, name: '睡觉', isDone: false },
      { id: 3, name: '打豆豆', isDone: true }
    ]
  }
}
  • App.vue通过父传子,把每一个循环的数据传递给子组件
<todo 
    v-for="item in list" 
    :key="item.id" 
    :item="item">
</todo>
  • todo.vue接受数据,且渲染
export default {
  props: ['item']
}
<li :class="{'completed': item.isDone}">
    <div class="view">
        <input class="toggle" type="checkbox" :checked="item.isDone">
        <label>{{item.name}}</label>
        <button class="destroy"></button>
    </div>
</li>

删除

  • 给删除按钮注册点击事件
<button class="destroy" @click="del(item.id)"></button>
  • 通过$emit把值传给父组件
methods: {
  del (id) {
    this.$emit("onedel",id);
  }
}
  • 父组件中的子组件 注册事件
<todo 
    v-for="item in list" 
    :key="item.id" 
    :item="item"
    @onedel="del">
</todo>
  • 父组件通过回调函数接受参数
methods: {
  del (id) {
      this.list = this.list.filter(item => item.id !== id);
  },
}

修改:不做了!下面代码其实就是我想让大家练习

  • 给checkbox注册change事件
<input class="toggle" type="checkbox" :checked="item.isDone" @change="change(item.id)">
  • 子传父,让父组件修改
change(id){
    this.$emit("onechange",id);
},
  • 父组件中的子组件注册事件
<todo 
    v-for="item in list" 
    :key="item.id" 
    :item="item" 
    @onechange="change"
    @onedel="del">
</todo>
  • 父组件修改状态
change (id) {
    const result = this.list.find(item => item.id === id)
    result.isDone = !result.isDone;
},

添加

  • 父级组件中通过v-model获取到任务的名字
<input class="new-todo" placeholder="输入新计划" autofocus v-model="name" @keyup.enter="add">

data () {
  return {
    name: ''
  }
},
  • 回车的时候,获取数据,把数据添加到数组中,且清空数据;
methods: {
  add () {
      this.list.unshift({
          id: Date.now(),
          name:this.name,
          isDone: false
      });
      this.name = "";
  },
}

剩余数量

  • 剩余数量:计算属性 统计没有完成的任务的数组
computed:{
    // 没有完成的数组
    left_list:function () {  
        return this.list.filter(item=>item.isDone==false).length;
    },
},
  • 视图中使用
<span class="todo-count">剩余<strong>{{left_list}}</strong>未完成 </span>

清空已完成

  • 清空:筛选没有任务的数组,把this.list重新赋值
<button class="clear-completed" @click="clear">清除已完成</button>
clear(){
    this.list = this.list.filter(item=>item.isDone==false);
}

小选与大选

  • 小选:设置计算属性,统计是否所有任务全部完成
ck_all:(value){
    return this.list.every(item=>item.isDone==true);  find filter every sort reduce slice 
}
  • 设置给全选按钮:
<input id="toggle-all" class="toggle-all" type="checkbox" :checked="ck_all">
  • 大选:
  • 需要获取全选按钮的状态值,需要把:checked="ck_all" 改为 v-model="ck_all"
  • 计算属性如果被修改,需要用到完整写法
ck_all:{
    get(){
        return this.list.every(item=>item.isDone);
    },
    set(value){
        this.list.forEach(item => item.isDone = value);
    }
}

筛选:作业

  • tab栏样式切换:注册点击事件,传入不同的状态;根据获取的不同状态进行类名选择
<li>
    <a :class="{'selected':status=='all'}" href="#/" @click="select('all')">全部</a>
</li>
<li>
    <a :class="{'selected':status=='none'}" href="#/active" @click="select('none')">未完成</a>
</li>
<li>
    <a :class="{'selected':status=='done'}" href="#/completed" @click="select('done')">已完成</a>
</li>
  • 执行函数:初始化赋值为status:'all'
select(status){
    this.status = status;
}
  • 选择不同的状态,就展示不同的数据,那么数据是由状态决定的,计算属性
// 展示的列表
show:function () {
    let arr;  
    switch (this.status) {
        case "all":
            arr = this.list;
            break;

        case "none":
            arr = this.list.filter(item=>item.isDone==false);
            break;

        case "done":
            arr = this.list.filter(item=>item.isDone==true);
            break;
    }
    return arr;
}
  • 循环遍历数据更换为:v-for="item in show"

本地存储

  • 把数据真实保留浏览器上,这样的话大家刷新完页面后,数据状态还是不变!
  • 做本地存储:
  • 侦听器:只需要写一个地方,专门用于侦听list;如果变,直接保存到本地;
  • 数据发生改变的时候存:【老办法:考虑很多地方!本地存储遍地开花】
    • 新增:做了
    • 修改:没有具体函数,做本地存储,貌似不好做了!
    • 删除:做了
    • 清除已完成:做了!
  • 监视数组的变化
watch: {
  list: {
    deep: true,
    handler(newValue) {
      localStorage.setItem('todoList', JSON.stringify(newValue))
    }
  }
}
  • data中默认使用本地的数据
data(){
    return {
        list: JSON.parse(localStorage.getItem('todoList')) || [],
    }
},

作业

附加练习_1.喜欢小狗狗吗

目标: 封装Dog组件, 用来复用显示图片和标题的

效果:

image-20210115103545558


正确答案(==先不要看==)

components/practise/Dog1.vue

<template>
  <div class="my_div">
    <img
      src="
      alt=""
    />
    <p>这是一个孤独可怜的狗</p>
  </div>
</template>

<script>
export default {};
</script>

<style>
.my_div {
  width: 200px;
  border: 1px solid black;
  text-align: center;
  float: left;
}

.my_div img {
  width: 100%;
  height: 200px;
}
</style>

在App.vue中使用

<template>
  <div>
    <Dog></Dog>
    <Dog/>
  </div>
</template>

<script>
import Dog from '@/components/practise/Dog1'
export default {
  components: {
    Dog
  }
}
</script>

<style>

</style>

总结: 重复部分封装成组件, 然后注册使用

附加练习_2.点击文字变色

目标: 修改Dog组件, 实现组件内点击变色

提示: 文字在组件内, 所以事件和方法都该在组件内-独立

图示:

10.3.1_组件_事件变量使用

正确代码(==先不要看==)

components/practise/Dog2.vue

<template>
  <div class="my_div">
    <img
      src="
      alt=""
    />
    <p :style="{backgroundColor: colorStr}" @click="btn">这是一个孤独可怜的狗</p>
  </div>
</template>

<script>
export default {
  data(){
    return {
      colorStr: ""
    }
  },
  methods: {
    btn(){
      this.colorStr = `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)})`
    }
  }
};
</script>

<style>
.my_div {
  width: 200px;
  border: 1px solid black;
  text-align: center;
  float: left;
}

.my_div img {
  width: 100%;
  height: 200px;
}
</style>

附加练习_3. 循环展示狗狗

目标: 把数据循环用组件显示铺设

数据:

[
    {
        dogImgUrl:
        "
        dogName: "博美",
    },
    {
        dogImgUrl:
        "
        dogName: "泰迪",
    },
    {
        dogImgUrl:
        "
        dogName: "金毛",
    },
    {
        dogImgUrl:
        "
        dogName: "哈士奇",
    },
    {
        dogImgUrl:
        "
        dogName: "阿拉斯加",
    },
    {
        dogImgUrl:
        "
        dogName: "萨摩耶",
    },
]

图示:

image-20210115112811452

正确代码(==不可复制==)

components/practise/Dog3.vue

<template>
  <div class="my_div">
    <img :src="imgurl" alt="" />
    <p :style="{ backgroundColor: colorStr }" @click="btn">{{ dogname }}</p>
  </div>
</template>

<script>
export default {
  props: ["imgurl", "dogname"],
  data() {
    return {
      colorStr: "",
    };
  },
  methods: {
    btn() {
      this.colorStr = `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(
        Math.random() * 256
      )}, ${Math.floor(Math.random() * 256)})`;


    },
  },
};
</script>

<style scoped>
.my_div {
  width: 200px;
  border: 1px solid black;
  text-align: center;
  float: left;
}

.my_div img {
  width: 100%;
  height: 200px;
}
</style>

App.vue引入使用把数据循环传给组件显示

<template>
  <div>
    <Dog v-for="(obj, index) in arr"
    :key="index"
    :imgurl="obj.dogImgUrl"
    :dogname="obj.dogName"
    ></Dog>
  </div>
</template>

<script>
import Dog from '@/components/practise/Dog3'
export default {
  data() {
    return {
      // 1. 准备数据
      arr: [
        {
          dogImgUrl:
            "
          dogName: "博美",
        },
        {
          dogImgUrl:
            "
          dogName: "泰迪",
        },
        {
          dogImgUrl:
            "
          dogName: "金毛",
        },
        {
          dogImgUrl:
            "
          dogName: "哈士奇",
        },
        {
          dogImgUrl:
            "
          dogName: "阿拉斯加",
        },
        {
          dogImgUrl:
            "
          dogName: "萨摩耶",
        },
      ],
    };
  },
  components: {
    Dog
  }
};
</script>

附加练习_4.选择喜欢的狗

目标: 用户每点击一次狗狗的名字, 就在右侧列表多显示一次名字

效果:

11.5_喜欢的狗狗

正确代码(==不可复制==)

components/practise/Dog4.vue

<template>
  <div class="my_div">
    <img :src="imgurl" alt="" />
    <p :style="{ backgroundColor: colorStr }" @click="btn">{{ dogname }}</p>
  </div>
</template>

<script>
export default {
  props: ["imgurl", "dogname"],
  data() {
    return {
      colorStr: "",
    };
  },
  methods: {
    btn() {
      this.colorStr = `rgb(${Math.floor(Math.random() * 256)}, ${Math.floor(
        Math.random() * 256
      )}, ${Math.floor(Math.random() * 256)})`;

      // 补充: 触发父级事件
      this.$emit("love", this.dogname);
    },
  },
};
</script>

<style scoped>
.my_div {
  width: 200px;
  border: 1px solid black;
  text-align: center;
  float: left;
}

.my_div img {
  width: 100%;
  height: 200px;
}
</style>

App.vue

<template>
  <div>
    <Dog
      v-for="(obj, index) in arr"
      :key="index"
      :imgurl="obj.dogImgUrl"
      :dogname="obj.dogName"
      @love="fn"
    ></Dog>

    <hr />
    <p>显示喜欢的狗:</p>
    <ul>
      <li v-for="(item, index) in loveArr" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>

<script>
import Dog from "@/components/practise/Dog4";
export default {
  data() {
    return {
      // 1. 准备数据
      arr: [
        {
          dogImgUrl:
            "
          dogName: "博美",
        },
        {
          dogImgUrl:
            "
          dogName: "泰迪",
        },
        {
          dogImgUrl:
            "
          dogName: "金毛",
        },
        {
          dogImgUrl:
            "
          dogName: "哈士奇",
        },
        {
          dogImgUrl:
            "
          dogName: "阿拉斯加",
        },
        {
          dogImgUrl:
            "
          dogName: "萨摩耶",
        },
      ],
      loveArr: []
    };
  },
  components: {
    Dog,
  },
  methods: {
    fn(dogName) {
      this.loveArr.push(dogName)
    },
  },
};
</script>

<style >
</style>

未完待续, 同学们请等待下一期

全套笔记资料代码移步: 前往gitee仓库查看

感兴趣的小伙伴可以自取哦,欢迎大家点赞转发~

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

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

相关文章

Spring: 在SpringBoot项目中解决前端跨域问题

这里写目录标题 一、什么是跨域问题二、浏览器的同源策略三、SpringBoot项目中解决跨域问题的5种方式&#xff1a;使用CORS1、自定 web filter 实现跨域(全局跨域)2、重写 WebMvcConfigurer(全局跨域)3、 CorsFilter(全局跨域)4、使用CrossOrigin注解 (局部跨域) 一、什么是跨域…

稀碎从零算法笔记Day34-LeetCode:最小栈

感谢耶稣&#xff0c;笔者又过了一天“复活节”。月末斩杀一道Hard画上句号 题型&#xff1a;栈、模拟数据结构 链接&#xff1a;155. 最小栈 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 设计一个支持 push &#xff0c;pop &#xff0c;…

适用于 Windows 的 6 个最佳视频转换器

视频转换器可以帮助您在设备上转换和播放不受支持的视频格式。它还可以方便地减小视频文件大小、以通用格式组织所有视频或与其他人共享文件以在不同设备上播放。 Windows 有大量视频转换器可供选择。虽然有些是免费的&#xff0c;但其他一些则提供迎合专业用户的高级功能。在…

Pycharm选择使用Anaconda环境中的Pytorch 失败解决办法之一

前几日想要复现一篇论文&#xff0c;结果给配的台式机完全禁不住&#xff0c;老是报溢出&#xff0c;慢都没事&#xff0c;溢出就很难受了&#xff0c;因此想用自己笔记本的GPU来训练。 安装以后遇到一个问题&#xff1a; Anaconda里创建了环境&#xff0c;安装好了对应pytor…

AR智能眼镜解决方案_MTK平台安卓主板硬件芯片方案开发

AR智能眼镜&#xff0c;是一个可以让现场作业更智能的综合管控设备。采用移动互联网、大数据和云计算等技术&#xff0c;现场数据的采集与分析&#xff1b;同时实现前端现场作业和后端管理的实时连动、信息的同步传输与存储。让前端现场作业更加智能&#xff0c;后端管理更加高…

再次加深理解Java中的并发编程

目录 一、线程、进程、程序 二、线程状态 三、线程的七大参数 四、lock与synchronized锁机制 一&#xff09;、lock与synchronized锁区别 二&#xff09;、synchronized锁原理 三&#xff09;、Lock锁原理 五、synchronized锁升级原理 一&#xff09;、锁升级基础知识 …

【Web】NSSCTF Round#20 Basic 两道0解题的赛后谈

目录 前言 baby-Codeigniter 组合拳&#xff01; 前言 本想着说看看go的gin框架就睡了的&#xff0c;r3师傅提醒说赛题环境已经上了&#xff0c;那不赶紧研究下&#x1f600; 主要来谈谈做题的心路历程 baby-Codeigniter 拿到题目的第一反应应该是&#xff1a;“什么是C…

C之易错注意点转义字符,sizeof,scanf,printf

目录 前言 一&#xff1a;转义字符 1.转义字符顾名思义就是转换原来意思的字符 2.常见的转义字符 1.特殊\b 2. 特殊\ddd和\xdd 3.转义字符常错点----计算字符串长度 注意 &#xff1a; 如果出现\890,\921这些的不是属于\ddd类型的&#xff0c;&#xff0c;不是一个字符…

SOA-面向服务架构

SOA-面向服务架构 1.概述2.SOA的设计原则包括&#xff1a;3. SOA实现方法1.Web Service2. 服务注册表3. 企业服务总线 细讲 超赞笔记 1.概述 SOA &#xff08;Service-Oriented Architecture&#xff0c;SOA&#xff09;&#xff0c;从应用和原理的角度&#xff0c;目前有2种…

书生·浦语大模型-第一节课笔记

视频总结 23年发布的模型在一些材料中归位指令微调模型&#xff0c;后面逐渐升级应该已经是train的模型了 技术报告总结 InternLM2 Technical Report 评测与特点 6 dimensions and 30 benchmarks, long-context modeling, and open-ended subjective evaluations长文本…

【软件工程】概要设计

1. 导言 1.1 目的 该文档的目的是描述学生成绩管理系统的概要设计&#xff0c;其主要内容包括&#xff1a; 系统功能简介 系统结构简介 系统接口设计 数据设计 模块设计 界面设计 本文的预期读者是&#xff1a; 项目开发人员 项目管理人员 项目评测人员&#xff08;…

C++:数据类型—字符串(11)

字符串就是包含多个字符组成的一个串 比如字符a,b&#xff0c;单个字符就是字符 那么"hello world" 就是一串字符组成的一个字符串 注意字符要在双引号里引用上&#xff0c;而字符一般都是单引号引用 在c中有两种定义字符串的方法&#xff0c;一个是原始c语言的定义方…

swift中的autoreleasepool(自动释放池)有用么?

想到一个问题 swift中的autoreleasepool(自动释放池)有用么? 我们进行验证一下 首先我们写一个加载图片的方法,保证会真正用到真实的IMP内存func loadBigData(string: String?) {if let path Bundle.main.path(forResource: "big", ofType: "png") {for…

二十四种设计模式与六大设计原则(二):【门面模式、适配器模式、模板方法模式、建造者模式、桥梁模式、命令模式】的定义、举例说明、核心思想、适用场景和优缺点

接上次博客&#xff1a;二十四种设计模式与六大设计原则&#xff08;一&#xff09;&#xff1a;【策略模式、代理模式、单例模式、多例模式、工厂方法模式、抽象工厂模式】的定义、举例说明、核心思想、适用场景和优缺点-CSDN博客 目录 门面模式【Facade Pattern】 定义 举…

vitess执行计划缓存 测试

打开执行计划器缓存&#xff1a; sysbench /usr/local/share/sysbench/oltp_write_only.lua --mysql-host127.0.0.1 --mysql-port15306 --mysql-userroot --mysql-password --mysql-dbcustomer --report-interval10 100s sysbench /usr/local/share/sysbench/oltp_read_only.l…

9.动态规划——1.从递归到动态规划

例题——N阶楼梯上楼问题 分析 大事化小&#xff1a;爬N层有F(N)种可能&#xff0c;有 F ( N ) F ( N − 1 ) F ( N − 2 ) F(N)F(N-1)F(N-2) F(N)F(N−1)F(N−2)小事化了&#xff1a; F ( 1 ) 1 &#xff0c; F ( 2 ) 2 F(1)1&#xff0c;F(2)2 F(1)1&#xff0c;F(2)2 …

小白从0学习ctf(web安全)

文章目录 前言一、baby lfi&#xff08;bugku-CTF&#xff09;1、简介2、解题思路1、解题前置知识点2、漏洞利用 二、baby lfi 2&#xff08;bugku-CTF&#xff09;1.解题思路1、漏洞利用 三、lfi&#xff08;bugku CTF&#xff09;1、解题思路1、漏洞利用 总结 前言 此文章是…

【Redis】Redis 生产问题。如何确保缓存和数据库数据的一致性? 常见的缓存更新策略?

目录 缓存穿透 缓存穿透解决办法 缓存击穿 击穿解决办法&#xff1f; 缓存穿透和缓存击穿的区别&#xff1f; 缓存雪崩 雪崩解决办法&#xff1f; 如何确保缓存和数据库数据的一致性&#xff1f; 常见的缓存更新策略&#xff1f; 缓存穿透 定义&#xff1a;缓存穿透说…

npm mongoose包下载冲突解决之道

我在新电脑下载完项目代码后,运行 npm install --registryhttps://registry.npm.taobao.org 1运行就报错&#xff1a; npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree npm ERR! npm ERR! While resolving: lowcode-form-backend1.0.0 npm …

rabbitMQ的基础操作与可视化界面

当你安装好RabbitMq时&#xff0c;可以 尝试一下&#xff0c;这些命令 启动rabbitMQ服务 #启动服务 systemctl start rabbitmq-server #查看服务状态 systemctl status rabbitmq-server #停止服务 systemctl stop rabbitmq-server #开机启动服务 systemctl enable rabbitmq-…