Following up on the last article, after familiarizing yourself with the basics of Vue3.0 and using it for a while, you are ready to develop a PC component library for vue3.0 use. There will be some new component library writing and notes, interested students can pay more attention to oh, not bb, start.

Develop a caroute map component, suitable for PC, (not considering APP), used in VUe3.0 + TS

The rough implementation looks like this:

Picture free rotation, corresponding dot picture jump, left and right indicator jump, etc. The following options configuration is exposed:

The above are the main options. Now I will expand them to show how to package them.

One: encapsulate ideas

The core idea of encapsulating components in VUe3.0 and VUe2.0 is the same, and vue.component() is needed. Register the component and use it by mounting it in main.ts.

Create it under SRC: SRC –> libs –> sqm_ui(the name of your UI library) –>index.js

Here, index.js is the entry to register the component.

Create a new file in the sibling directory, Carousel, that contains all the features and styles of the multicast components.

The directory is as follows:

One thing to note: although used in VUe3.0 and TS, the entry file is still js so that it can be written in a non-TS format.

Js: in the index.

import Carousel from './Carousel/carousel'; import CarItem from './Carousel/item'; let SqmUI = {}; SqmUI.install = function(vue) { vue.component(Carousel.name, Carousel); vue.component(CarItem.name,CarItem); }; export default SqmUI;Copy the code

But in order to work with TS, we need to create a new index.d.ts file that describes the library member types for TS.

declare const _default: ({ install: (app: import("vue").App<any>, ... options: any[]) => any; Install}); export default _default;Copy the code

After the above configuration, use the following command in main.ts:

import SqmUI from '@/libs/sqm_ui/index';
import { createApp } from 'vue';
createApp.use(SqmUI);
Copy the code

Two: encapsulation process

For the Carousel image, we need a fixed container to hold each scrolling image, so we need to define a carousel.vue component.

<template> <div class="carousel"> <slot></slot>Copy the code

You also need a component for storing photos, item.vue

<template> <div class="carousel-item"> <slot></slot>Copy the code

The basic framework is set up and options are configured in Carousel when the user uses it.

<carousel
    :autoPlay="true" 
    :durdation="3000" 
    :initial="3" 
    :hasDot="true" 
    :hasDirector="true"> </carousel>
Copy the code

In Carousel.vue: Accepts incoming configuration items

props: {       
    autoplay: {            
        type: Boolean,            
        default: true        },        
    duration: {           
        type: Number,            
        default: 3000        },       
    initial: {            
        type: Number,            
        default: 0        },  
    hasDot: {            
        type: Boolean,
        default: true        },        
    hasDirector: {  
        type: Boolean,          
        default: true        }
}
Copy the code

(1): Implement autoPlay:

On the carousel. The vue:

Const autoPlay = () => {if (props. AutoPlay) {t = setInterval(() => {// multicast logic}, props. Duration); }; onMounted(() => { autoPlay(); });Copy the code

Int autoPlay (mounted);

(2): Realize round seeding:

I want to ask this question: how can I make this picture show? The index of the current image must be equal to the index of the rotation before it can be displayed.

In the item. In the vue:

<div class="carsel-item" v-if="selfIndex === currentIndex">      
    <slot></slot> 
</div>
Copy the code

It can only be displayed if its index is equal to the current index.

Get currentIndex:

Built-in method in Vue3.0: getCurrentInstance()

This is an important method by which we can get an instance of the current component and then get the context of that component through CTX. Very useful.

In the item. In the vue:

setup() {
  const instance:any = getCurrentInstance();  console.log(instance);
}
Copy the code

Under instance.vnode there is a key that corresponds to each image itself, which is the index.

Under instance.parent. CTX there is a currentIndex defined, which is the currentIndex.

When the two are the same, the current image can be displayed. So where do I set currentIndex?

Back to Carousel.vue:

setup(props) {       
    const state = reactive({            
        currentIndex: props.initial,            
        itemLen: 0,            
        showDir: false        
    });
}
Copy the code

The current currentIndex is the value of the initial passed in.

In autoPlay: Perform rotation

const setIndex = ((dir:String): void => { switch(dir) { case 'next': state.currentIndex += 1; if (state.currentIndex === state.itemLen) { state.currentIndex = 0; } break; case 'prev': state.currentIndex -= 1; if (state.currentIndex === -1) { state.currentIndex = state.itemLen - 1; } break; default: break; }});Copy the code

When next, let currentIndex++; Until it’s equal to the length of the rotation picture. (array.length)

When prev, let currentIndex–; Until the = = = 1

Then listen in item.vue:

watch(() => {            
    return instance.parent.ctx.currentIndex    
    }, (value) => {            
    state.currentIndex = value; 
})
Copy the code

This completes the rotation of the picture.

Three: dot indicator

The idea of implementation is simple:

Determine if the display is required by the incoming hasDot. ItemLen is passed in to determine how many dots to display based on the number of images. Click on the dots to jump to the corresponding image.

On the dot. Vue:

<template>
    <div class="dot-goes-wrapper" v-if="hasDot">
        <div class="dot-item" v-for="item in itemLen" :key="item">
        <a href="javascript:;"
           class="dot-link"
            :style="{backgroundColor: (item - 1) === currentIndex ? dotBgColor : '#fff'}" 
             @click="dotClick(item - 1)">
        </a> 
        </div> 
    </div>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
export default defineComponent({
    name: 'dot',
    props: { 
        itemLen: Number, 
        currentIndex: Number,       
        dotBgColor: {           
             type: String,
             default: '#ff5000' },
        hasDot: {           
             type: Boolean,            
             default: true }    
    },    
    setup(props, ctx) {        
        const dotClick = (index: Number) => {  
            ctx.emit('dotClick', index); 
        };       
        return {           
            dotClick        
        }    
}})
</script>
Copy the code

Trigger dotClick via CTX to pass in index, used in parent component (carousel.vue):

@dotClick=”dotClick”

const dotClick = (index: any): void => {

state.currentIndex = index;

};

This completes the dot indicator.

Four: left and right indicators

This is very simple, is when moving in to show, and then click on the image to slide.

<template> <div v-if="showDir"> <div class="director dir-next" v-if="dir === 'next'"> <a href="javascript:;" @click="dirClick(dir)">&gt; </a> </div> <div class="director dir-prev" v-else-if="dir === 'prev'"> <a href="javascript:;" @click="dirClick(dir)">&lt; </a> </div> </div> </template> <script lang="ts"> import {defineComponent} from 'vue'; export default defineComponent({ name: 'direct', props: { dir: String, showDir: { type: Boolean, default: false } }, setup(props, ctx) { const dirClick = (dir: String) => { ctx.emit('dirClick', dir); }; return { dirClick } } })</script>Copy the code

Similarly, pass a dirClick event to the parent component and perform click and move in the parent component.

Five: Finally:

Because the wheel map is implemented through the timer need to destroy the timer.

onBeforeUnmount(() => {

      _clearFunction();

});

function _clearFunction(): void {

     clearInterval(t);

       t= null;

};

Stop the auto play when the mouse moves in, and display the left and right indicators:

const mouseEnter = (): void => {      
      _clearFunction();
     state.showDir = true;
 };  
Copy the code

When the mouse moves out, the left and right indicators disappear

 const mouseLeave = (): void => { 
         autoPlay();
         state.showDir = false; 
};
Copy the code

Ok. That’s the general idea, and you can think about some details for yourself. Thank you!!!!!

Six: Looking back

Vue3.0 project construction and use process juejin.cn/post/691762…