Da Shuai just made a version of tantan’s flying card effect components, very cool!
Unfortunately, it’s not vuE3. Here’s how to do it correctly.
Absolute plagiarism, if there is a difference, pure coincidence 😁
Video version
For those of you who like to watch the video, go here: Vue 3.0 fakes the flycard component
Flying card principle
There are three core points: card stacking layout, dragging cards and flying cards
The layout mainly uses z-index and Absolute positioning.
Drag the main use of a few touch events: touchstart, touchmove, touchcancel, touchend;
Feka mainly uses the Pythagorean theorem 😁
See the original text for details.
componentization
Here, the extracted component is the core, so let’s take a look at the structure of the FlyCard component template:
<div>
<div>
<div class="card"
@touchstart="touchStart"
@touchmove="touchMove"
@touchcancel="touchCancel"
@touchend="touchCancel">
<slot name="firstCard"></slot>
</div>
<div class="card">
<slot name="secondCard"></slot>
</div>
<div class="card">
<slot name="thirdCard"></slot>
</div>
<div class="card">
</div>
</div>
</div>
Copy the code
Notice that all styles are omitted, all views are replaced with divs, and each card has named slots for incoming content.
Only card 1 needs to monitor events, and finally reserve an empty card to wait for “upper” 😁
So, when you use the FlyCard component, you need to distribute the content using the V-slot directive. Take a look at Demo-Tan.vue
<fly-card>
<template #firstCard>
<div v-if="cards[0]" class="tantanCard">
<img :src="cards[0].img" mode="aspectFill" />
</div>
</template>
<! -- omit several other templates -->
</fly-card>
Copy the code
Note that vite is used here, and the image SRC is set dynamically. Special processing is required, otherwise it will not display normally:
import img1 from ".. /assets/1.jpg"; Copy the code
cards: [{img: img1}] Copy the code
Logical code split
Currently FlyCard is approaching 400 lines, which is not very easy to maintain, so we can break them up using the Composition API.
It is not difficult to observe that the drag logic is only needed by card 1, so the data and logic control in this part are independent and can be separated completely.
Create use/touch. Js and extract this logical code.
- Extract the useTouch function, receive card attributes and callback functions, etc
- The response data is left and top above
- The logic that controls them is touchStart and things like that
- Organized together and exported for external use, which can be reused later on in other projects
Extract useTouch, the interface is as follows:
function useTouch(props, { onDragStart, onDragMove, onDragStop, onThrowStart, onThrowDone, onThrowFail, }) {}
Copy the code
The calculation logic is used after passing in card attributes, and event callbacks are allowed so that the outside world can do something extra:
Reactive data creation
const cardOneState = reactive({
left: 0.top: 0.startLeft: 0.startTop: 0.isDrag: false.isThrow: false.needBack: false.isAnimating: false,})Copy the code
Control logic: Replace a lot of this. XXX, like the following:
function touchStart(e) {
if (cardOneState.isAnimating) return;
cardOneState.isDrag = true;
cardOneState.needBack = false;
cardOneState.isThrow = false;
/ /...
}
Copy the code
One exception to this is the getDistance method, which is a utility method that is not needed outside and can be placed inside utils.
Below are the fly-card logic and card rebound logic, which need to handle the state of several more cards
const otherCardsState = reactive({
left2: 0.top2: 0.width2: 0.height2: 0.// ...
});
function resetAllCardDown() {/ *... * /}
function resetAllCard() {/ *... * /}
function makeCardThrow() {/ *... * /}
function makeCardBack() {/ *... * /}
Copy the code
Lifecycle hook handling
import { onMounted } from "vue";
function useTouch() {
// ...
onMounted(() = > {
resetAllCard()
})
}
Copy the code
Finally, export interface:
return{... toRefs(cardOneState), ... toRefs(otherCardsState), touchStart, touchMove, touchCancel, };Copy the code
The reconstruction is complete. UseTouch () looks like this
In-component use
Now use the useTouch in FlyCard, with the additional emits option exposed, to make the component input and output more explicit.
import useTouch from ".. /use/touch";
export default {
props: {},
emits: [
"onDragStart"."onDragMove"."onDragStop"."onThrowFail"."onThrowStart"."onThrowDone",].setup(props, { emit }) {
const touchState = useTouch(props, {
onDragStart: () = > emit("onDragStart"),
onDragMove: (obj) = > emit("onDragMove", obj),
onDragStop: (obj) = > emit("onDragStop", obj),
onThrowFail: () = > emit("onThrowFail"),
onThrowStart: () = > emit("onThrowStart"),
onThrowDone: () = > emit("onThrowDone")});return{... touchState }; }};Copy the code
You can see that the FlyCard component is much cleaner, shrinking from nearly 400 lines to 200
On the blackboard
Now that the refactoring is complete, this is our little exercise in using the Vue3 Composition API, and the benefits are obvious:
- Our components are cleaner and easier to maintain
- Our business logic is reusable
- Our code is completely erased
this
Is more conducive to supporting TS - During the refactoring process, we improved our understanding of the business. I didn’t write any of the code, but I quickly figured out which interfaces the components really needed and which methods were just internal to touch and didn’t need to be exposed.
thinking
If you look at the code for other cards, it’s very regular and should be easily abstracted into more general and reusable logic, such as whether I can specify the number of cards dynamically, rather than writing them down as I do now, which greatly limits its generality. I’ll leave that up to you to implement, so I can do pr for my project.
Code warehouse
Github.com/57code/flyc…
Video version
For those of you who like to watch the video, go here: Vue 3.0 fakes the flycard component
Pay attention to Village chief Yang
Say about this case here, hope to cast a brick to attract jade, draw out more good content to appear. My recent post (thanks for the encouragement and support of Digifriends 🌹🌹🌹) :
- 🔥 Another night, do you still feel short about this comic-API 198👍
- 🔥 win vue3 you need to prepare 62👍
- 🔥 Lightning Five Whip: An in-depth analysis of Composition API 49👍
- 🔥 my special 2020 | 35 👍 Denver annual essay
My video tutorial (thanks for digg friends encouragement and support 🌹🌹🌹) :
- Vue3.0 Speed overhand “continuously updated” 523👍
- [Face bully nurseries] make wheels every day (a more every day, suggested collection) 69👍
- Vue3 village head source analysis 60👍
- 【 happy 1024】 to programmer compatriots online hair wife! 31 👍