vue-day05
1-父组件向子组件通信
- 通过子自定义属性的方式实现父组件向子组件传递数据
1.1-步骤
-
在父组件中, 找到子组件的调用标签, 通过自定义属性的方式将父组件中的数据传递给子组件
<List v-bind:dataList="list"/>
export default { data() { return { list:[ { id:2, title:'军事新闻', content:'军事新闻内容' }, { id:1, title:'财经新闻', content:'财经新闻内容' } ] }; } }
-
在子组件中, 通过props属性来接收父组件通过自定义属性传递的数据
export default { // 接收父组件传递过来的数据 // 写法1 props:['dataList'] }
<tr v-for="item in dataList" :key="item.id"> <td>{{item.id}}</td> <td>{{item.title}}</td> <td width="40%">{{item.content}}</td> <td> <button>编辑</button> <button>删除</button> </td> </tr>
1.2-对props数据的类型进行校验
-
数据类型可选值: String, Number, Boolean, Array, Object, Null, Undefined
-
当父组件传递的数据和要求的类型不匹配的时候, 并不会影响功能, 只会在控制台下面给出红色警告
export default { // 写法2: 校验数据类型, // props:{ // dataList:[Array] // } // 写法3:指定默认值&校验数据类型 props:{ dataList:{ // 指定默认值: 当默认值为数组或对象的时候, 必须采用函数的方式 default(){ return [ { id:1, title:'财经新闻', content:'财经新闻内容' } ] }, // 校验数据类型 type:[Array,Object] } } }
1.3-props数据和data数据的区别
- props数据是来自外界的数据
- 如果props数据是基本数据类型(String,Number,Boolean), 那么只能读取, 不能重写
- 如果props数据是引用数据类型(Array,Object), 那么可读可写
- data数据是组件内部的数据, data数据是可读可写的
2-子组件向父组件通信
- 通过自定义事件实现子组件向父组件传递数据
2.1-步骤
-
在父组件中, 找到子组件的调用标签, 通过v-on注册一个自定义事件, 自定义事件处理函数需要在父组件的methods中提前声明
<List :dataList="list" v-on:del="del"/>
export default { methods: { // 自定义事件del的处理函数:通过形参接收子组件通过this.$emit方法传递的数据 del(id){ // 1-通过id查找索引 const index=this.list.findIndex(item=>item.id===id); // 2-通过索引删除数组元素 this.list.splice(index,1); } } }
-
在子组件中, 通过
this.$emit('自定义事件的名称',需要传递的数据)
触发自定义事件<tr v-for="item in dataList" :key="item.id"> <td>{{item.id}}</td> <td>{{item.title}}</td> <td width="40%">{{item.content}}</td> <td> <button @click="del(item.id)">删除</button> </td> </tr>
export default{ methods:{ del(id){ // 通过this.$emit()触发自定义事件 this.$emit('del',id); } } }
3-非父子组件之间通信
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M9oa4CrE-1609983820245)(media/非父子组件通信.gif)]
- 使用自定义事件的方式实现非父子组件之间的数据通信
3.1-步骤
-
创建一个空的vue实例vm, 充当事件中心的角色
utils/vm.js
// 导入vue import Vue from 'vue'; // 创建vue实例对象 const vm=new Vue(); // 导出 export default vm;
-
在A组件中, 通过
vm.$emit('自定义事件名称','数据')
触发自定义事件components/List.vue
<tr v-for="item in dataList" :key="item.id"> <td>{{item.id}}</td> <td>{{item.title}}</td> <td width="40%">{{item.content}}</td> <td> <button @click="edit(item)">编辑</button> </td> </tr>
// 导入事件中心 import vm from '../utils/vm' export default { methods: { // 编辑按钮的点击事件处理函数 edit(row){ // 通过事件中心vm.$emit()触发自定义事件 vm.$emit('editContent',row); } } }
-
在B组件中, 通过
vm.$on('自定义事件的名称',事件处理函数)
监听自定义事件components/Modal.vue
// 导入事件中心vm import vm from '../utils/vm'; export default { created(){ // 通过vm.$on()监听自定义事件editContent vm.$on('editContent',(row)=>{ // row就是兄弟组件List中传递过来的数据 console.log(row); }); } }
4-ref属性
-
虚拟DOM对象: 一个描述标签的属性和标签嵌套关系的特殊对象
const img={ name:'img', attributes:{ src:'./imgs/01.jpg', alt:'', title:'这是一张图片' } } const div={ name:'div', attributes:{ title:'', className:'', style:'' }, children:[ '这是div的内容', img ] }
4.1-ref属性操作标签
-
在目标元素上添加一个ref属性, 保证ref属性的值不重复
<div ref="box"></div>
-
逻辑层, 可以通过
this.$refs.ref属性名
获取目标元素对应的虚拟Dom对象// 获取标签对象 this.$refs.box
4.2-ref属性操作组件
-
在组件调用标签上添加一个ref属性, 保证ref属性的值不重复
<Box ref="box1"/>
-
在逻辑层, 可以通过
this.$ref.ref属性名
获取组件对象, 从而调用组件中的数据和方法// 获取组件对象 this.$refs.box1 // 获取组件视图对象 this.$refs.box1.$el
6-vue项目中引入jquery
-
安装
npm i jquery -S
-
使用
// 1-导入 import $ from 'jquery';
7-vue中使用swiper轮播图插件
-
安装
npm i swiper@3.4.1 -S
-
使用
<div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide"> <img src="../assets/imgs/slider/01.jpg" alt=""> </div> <div class="swiper-slide"> <img src="../assets/imgs/slider/02.jpg" alt=""> </div> <div class="swiper-slide"> <img src="../assets/imgs/slider/03.jpg" alt=""> </div> </div> <!-- Add Pagination --> <div class="swiper-pagination"></div> <!-- Add Arrows --> <div class="swiper-button-prev"></div> <div class="swiper-button-next"></div> </div>
// 导入swiper核心文件 import Swiper from 'swiper/dist/js/swiper'; // 导入swiper样式 import 'swiper/dist/css/swiper.min.css' export default { mounted(){ this.init(); }, methods:{ // 轮播图初始化 init(){ var swiper = new Swiper('.swiper-container', { pagination: '.swiper-pagination', effect: 'flip', grabCursor: true, nextButton: '.swiper-button-next', prevButton: '.swiper-button-prev', loop:true }); } } }
.swiper-slide img{ width: 100%; }
8-插槽
- 作用: 外部向组件内部传递数据的一种形式, 传递的是标签结构
8.1-匿名插槽
-
定义
<template> <div class="cmt-container"> <!-- 使用slot标签进行占位 --> <slot></slot> <div> <button>提交评论</button> </div> </div> </template> <script> export default { } </script> <style> .cmt-container{ width: 600px; height: 200px; background: #EEE; margin: 60px auto; } </style>
-
调用
<!-- 调用组件 --> <Comment> <div> <input type="text" placeholder="请输入评论内容" /> </div> <div> <input type="text" placeholder="请输入昵称"> </div> </Comment>
8.2-具名插槽
-
定义
<template> <div class="form"> <slot name="header"></slot> <div> <div> <input type="text" placeholder="请输入用户名"/> </div> <div> <input type="text" placeholder="请输入密码"/> </div> </div> <slot name="footer"></slot> </div> </template> <script> export default { } </script> <style> .form{ width: 600px; height: 200px; margin:20px auto; background-color: #EEE; } </style>
-
调用
<MyForm> <div slot="header"> <h3>会员注册</h3> </div> <div slot="footer"> <button>立即注册</button> </div> </MyForm>
8.3-作用域插槽
-
定义
<template> <div class="table-container"> <table cellpadding="0" cellspacing="0" width="100%"> <thead> <tr class="active"> <td v-for="(item,index) in titles" :key="index">{{item}}</td> </tr> </thead> <tbody> <tr v-for="item in dataList" :key="item.id"> <td>{{item.id}}</td> <td>{{item.name}}</td> <td>{{item.ctime}}</td> <td> <!-- 1-占位 2-向外分发数据, 通过自定义属性的方式分发数据 --> <slot :row="item" :brandName="item.name"></slot> </td> </tr> </tbody> </table> </div> </template> <script> export default { // 接收父组件传递的数据 props:['titles','dataList'] }; </script> <style> .table-container { width: 800px; margin: auto; } tr { height: 50px; text-align: center; } .form-control { height: 40px; padding: 10px; width: 100%; border: 1px solid #ddd; border-radius: 4px; } .btn { border: 1px solid #ddd; width: 60px; line-height: 30px; text-align: center; color: #555; background: #eee; border-radius: 6px; cursor: pointer; font-weight: 700; outline: 0; } .active { background-color: #eee; } table, td { border: 1px solid #ccc; /* 合并边框 */ border-collapse: collapse; } .btn.danger { background-color: #d9534f; color: #fff; } .btn.success { background-color: #337ab7; color: #fff; } .line { border-bottom: 1px solid #ddd; margin: 10px 0; } </style>
-
调用
- 新写法:
v-slot="obj"
- 老写法:
slot-scope="obj"
<Table :titles="titles" :dataList="dataList"> <!-- 接收数据 obj: 自定义模板变量, 包含slot标签通过通过自定义属性分发的所有数据 --> <template v-slot="obj"> <button @click="del(obj.row)" class="btn danger">删除</button> <button class="btn success">编辑</button> </template> </Table>
- 新写法:
9-组件样式添加作用域
-
在组件内部的style标签上添加
scoped
属性即可<style scoped> </style>
9.1-实现原理
-
系统会自动生成一个随机的字符串, 如
data-v-31dc5552
-
系统会自动在调用选择器的标签上添加一个自定义属性
<div data-v-31dc5552="" class="container"><h1 data-v-31dc5552="">box组件</h1></div>
-
系统会使用随机生成字符串对组件内部的
css
选择器进行改写.container[data-v-31dc5552]{ width: 600px; height: 400px; background: pink; }
参考文档
ger">删除
编辑
9-组件样式添加作用域
-
在组件内部的style标签上添加
scoped
属性即可<style scoped> </style>
9.1-实现原理
-
系统会自动生成一个随机的字符串, 如
data-v-31dc5552
-
系统会自动在调用选择器的标签上添加一个自定义属性
<div data-v-31dc5552="" class="container"><h1 data-v-31dc5552="">box组件</h1></div>
-
系统会使用随机生成字符串对组件内部的
css
选择器进行改写.container[data-v-31dc5552]{ width: 600px; height: 400px; background: pink; }