在开始之前我去复习了一下,clientX、clientY、pageX、pageY的区别,对于不熟悉offsetLeft和offsetTop的也可以在这里去复习一下。
vue拖拽指令之offsetX、clientX、pageX、screenX_wade3po的博客-CSDN博客_vue offset
客户区坐标位置(clientX,clientY)
鼠标事件都是在浏览器视口中的特定位置发生的。这个位置信息保存在事件对象的clientX和clientY属性中,所有浏览器都支持这两个属性。
页面坐标位置(pageX,pageY)
pageX和pageY两个属性代表鼠标光标在页面中的位置,因此坐标是从页面本身而非视口的左边和顶边计算的。在没有滚动的情况下,clientX和cilentY与pageX和pageY是相等的
屏幕坐标位置(screenX,screenY)
鼠标事件发生的时候,不仅仅会有相对于浏览器的窗口,还有一个相对于整个电脑屏幕的位置。
代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script src="https://cdn.jsdelivr.net/npm/vue@2.7.10/dist/vue.js"></script><style>* {margin: 0;padding: 0;}.box {position: absolute;top: 0;left: 0;text-align: center;line-height: 100px;width: 100px;height: 100px;border-radius: 10%;background-color: greenyellow;margin-top: 10px;}</style>
</head><body><div id="root"><com-son :msg="haha"></com-son></div><template id="box"><div><h3 class="box" v-for="(item,idx) in dmsg" :key="idx" @mousedown="drag">{{item}}</h3></div></template><script>// 创建组件let ComSon = {template: "#box",props: ['msg'],data() {return {dmsg: this.msg}},methods: {drag(e) {//鼠标摁下事件var x = e.clientX - e.target.offsetLeft;var y = e.clientY - e.target.offsetTop;// console.log(x, y);//鼠标移动事件document.onmousemove = function (el) {e.target.style.left = el.pageX - x + 'px'e.target.style.top = el.pageY - y + 'px'},//鼠标抬起事件document.onmouseup = function () {// 设置随机颜色var bgc = 'rgb(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256)e.target.style.backgroundColor = bgc;document.onmousemove = null;}}}}Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示const vm = new Vue({el: '#root',data() {return {haha: ['宝子们', '周末愉快', '愉快吖', '哈哈', '~!!!', '这是', '作业哟']}},methods: {},components: {ComSon,}});</script>
</body></html>
效果图:
案列二:自定义事件的子传父
1、css板块代码
#root {width: 900px;height: 600px;padding: 10px;display: flex;justify-content: space-between;}.sh {width: 400px;height: 100%;background-color: rgb(233, 157, 157);padding: 10px;}.shop {width: 100%;height: 150px;background-color: white;display: flex;align-items: center;box-sizing: border-box;overflow: hidden;margin-bottom: 10px;}.bgcont {width: 400px;height: 100%;background-color: rgb(157, 231, 233);padding: 10px;}.shop img {width: 120px;margin-left: 10px;}.shop_context {margin: 0px 10px;}.shop_context>p {overflow: hidden;word-break: break-all;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;font-size: 14px;color: rgb(112, 111, 111);}.shop_context div {display: flex;justify-content: space-between;align-items: center;}.shop_context div>p {color: rgb(71, 70, 70);font-size: 14px;}.active {color: darkorange !important;}.son {width: 100%;height: 100%;background-color: #fff;display: flex;flex-direction: column;align-items: center;}.son img {margin-top: 20px;width: 270px;height: 290px;border: darkgrey 1px solid;}.son p {margin: 0px 20px;font-size: 15px;}.son h2:last-of-type {color: red;}.son button {border: none;width: 250px;height: 45px;border-radius: 10px;background-image: linear-gradient(to right top, #d16ba5, #c777b9, #ba83ca, #aa8fd8, #9a9ae1, #8aa7ec, #79b3f4, #69bff8, #52cffe, #41dfff, #46eefa, #5ffbf1);}
2、body部分
<body><div id="root"><div class="sh"><div class="shop" v-for="(item, index) in list" :key="index" @click="shopChuan(list[index])"><img :src="item.imgsrc" alt=""><div class="shop_context"><h3>{{item.name}}</h3><p>{{item.context}}</p><div><h3>¥{{item.price}}缘</h3><p v-text="item.flag == true?'已购买':'未购买'" :class="item.flag == true?'active':''"></p></div></div></div></div><div class="bgcont" v-if="isShow"><com-son :propsitem="propsitem" @haha="hahaha"></com-son></div></div>
3、vue代码
template代码是放在body中的,也可以将它写在组件里,依据个人喜好设置
<template id="son"><div class="son"><!-- <h1>子组件</h1> --><img :src="propsitem.imgsrc" alt=""><h3>{{propsitem.name}}</h3><p>{{propsitem.context}}</p><h3>¥{{propsitem.price}}缘</h3><button @click="change">点击购买</button></div></template><script>let ComSon = {template: "#son",props: {// 对象验证propsitem: {type: Object}},methods: {change() {if (this.propsitem.flag === true) {alert("已经购买过了~~~")return}this.$emit("haha", this.propsitem.id)alert("购买成功~~~")}}}const vm = new Vue({el: '#root',data() {return {list: [{id: 111,name: "小米平板5 Pro",imgsrc: "./img/tp3.png",context: "更大的屏幕,带来更强的拓展性高效的多任务处理灵活的多设备互联,你想做的每件事,从未如此得心应手小米平板5 Pro 12.4英寸生产力的更多可能性,由此展开。",price: 2999,flag: false,},{id: 222,name: "米家直驱洗烘一体机",imgsrc: "./img/tp2.png",context: "「以旧换新优惠50元,以旧换新到手价1949元!」「第六代DD直驱电机!智能洗烘!微蒸空气洗!高温杀菌,电机10年质保!」DD直驱电机/智能洗烘/微蒸空气洗/高温除螨洗/巴氏杀菌",price: 1999,flag: true,},{id: 333,name: "米家全能扫拖机器人",imgsrc: "./img/tp1.png",context: "免洗集尘全自动,一机解放双手,自动洗拖布 | 自动集尘 | 自动热烘干 | 自动补水 | 专用清洁剂,S-Cross AI™ 超感知立体识别避障系统,智能分配用水比例,拖地不中断",price: 3999,flag: false,},],isShow: false,propsitem: {}}},methods: {shopChuan(e) {this.isShow = trueconsole.log(e);this.propsitem = e},hahaha(b) {// console.log(b);for (let i of this.list) {if (i.id === b) {i.flag = true// console.log(i.id);}}}},components: {ComSon}})</script>
效果展示: