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 erasedthisIs 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 👍