This is the 8th day of my participation in Gwen Challenge
Review the
In the last article, we talked about what a component is and what tools you need to develop a component. After that, we took you through some minor changes to the webPack-template directory structure and configuration files. In this installment, we will introduce components into templates and how to debug and configure our components
For those of you who haven’t read the first article, please click on how to Pack front-end components with WebPack.
The import plug-in
Go back to the SRC/Components/better-draggable-ball/index.ts file we created in the previous article and paste in the plugin code we wrote earlier
// Plug-in code
interfaceDefaultPositionType { x? :number, y? :number
}
interfaceOptions { autoAdsorbent? :boolean; hideOffset? :number; defaultPosition? : DefaultPositionType; }export default class Drag {
/ / element
element: HTMLElement;
// Screen size
screenWidth: number;
screenHeight: number;
// Element size
elementWidth: number;
elementHeight: number;
isPhone: boolean;
// Coordinates of the current element
elementX: number;
elementY: number;
/ / element offset
elementOffsetX: number;
elementOffsetY: number;
// Whether to drag
moving: boolean;
/ / adsorption
autoAdsorbent: boolean;
/ / hide
hideOffset: number;
constructor(element: HTMLElement, dConfig: Options = {}) {
dConfig = this.InitParams(dConfig);
this.element = element;
this.screenWidth = window.innerWidth || window.outerWidth || 0;
this.screenHeight = window.innerHeight || window.outerHeight || 0;
this.elementWidth = this.element.offsetWidth || 0;
this.elementHeight = this.element.offsetHeight || 0;
this.isPhone = /(iPhone|iPad|iPod|iOS|Android)/i.test(navigator.userAgent);
this.element.style.position = 'absolute';
this.elementX = 0;
this.elementY = 0;
this.elementOffsetX = 0;
this.elementOffsetY = 0;
this.moving = false;
this.autoAdsorbent = dConfig.autoAdsorbent;
this.hideOffset = this.elementWidth * dConfig.hideOffset;
if (!this.isPhone) {
console.error('Warning!! The current plugin version is mobile only.);
}
// Default location
this.setElementPosition(dConfig.defaultPosition.x, dConfig.defaultPosition.y);
this.watchTouch();
}
protected InitParams(dConfig: Options):Options {
// Handle unconfigured parameters in Options
return {
autoAdsorbent: dConfig.autoAdsorbent || false.hideOffset: dConfig.hideOffset || 0.defaultPosition: dConfig.defaultPosition || { x: 0.y: 0}}; }private watchTouch(): void {
this.element.addEventListener('touchstart'.(event: TouchEvent) = > {
const rect = (event.target as HTMLElement).getBoundingClientRect();
// The height of the page to be rolled
// Not compatible with IE
const docScrollTop = document.documentElement.scrollTop;
this.elementOffsetX = event.targetTouches[0].pageX - rect.left;
this.elementOffsetY = event.targetTouches[0].pageY - rect.top - docScrollTop;
this.moving = true;
this.element.addEventListener('touchmove'.this.move.bind(this), { passive: false });
});
window.addEventListener('touchend'.() = > {
this.moving = false;
document.removeEventListener('touchmove'.this.move);
if (this.autoAdsorbent) this.adsorbent();
});
}
private setElementPosition(x: number.y: number) :void {
// Overflow processing
// Overflow scope
// But the page is out of the screen, calculate the current screen range
const leftScope = this.moving ? 0 : 0 - this.hideOffset;
// Maximum value of current screen right
const rs = this.screenWidth - this.elementWidth;
const rightScope = this.moving ? rs : rs + this.hideOffset;
const bottomScope = this.screenHeight - this.elementHeight;
if (x <= leftScope && y <= 0) {
[x, y] = [leftScope, 0];
} else if (x >= rightScope && y <= 0) {
[x, y] = [rightScope, 0];
} else if (x <= leftScope && y >= bottomScope) {
[x, y] = [leftScope, bottomScope];
} else if (x >= rightScope && y >= bottomScope) {
[x, y] = [rightScope, bottomScope];
} else if (x > rightScope) {
x = rightScope;
} else if (y > bottomScope) {
y = bottomScope;
} else if (x <= leftScope) {
x = leftScope;
} else if (y <= 0) {
y = 0;
}
this.elementX = x;
this.elementY = y;
this.element.style.top = `${y}px`;
this.element.style.left = `${x}px`;
}
private move(event: TouchEvent): void {
event.preventDefault();
if (!this.moving) return;
this.elementY = (event.touches[0].pageX - this.elementOffsetX);
this.elementX = (event.touches[0].pageY - this.elementOffsetY);
const ex = (event.touches[0].pageX - this.elementOffsetX);
const ey = (event.touches[0].pageY - this.elementOffsetY);
this.setElementPosition(ex, ey);
}
private animate(targetLeft: number.spd: number) :void {
const timer = setInterval(() = > {
let step = (targetLeft - this.elementX) / 10;
// Round up the step size if it is greater than 0 and round down if it is less than 0.
step = step > 0 ? Math.ceil(step) : Math.floor(step);
// Animation principle: Target position = current position + step size
const x = this.elementX + step;
this.setElementPosition(x, this.elementY);
// Check if the slow animation has stopped
if (Math.abs(targetLeft - this.elementX) <= Math.abs(step)) {
// Handle decimal assignments
const xt = targetLeft;
this.setElementPosition(xt, this.elementY);
clearInterval(timer);
}
}, spd);
}
private adsorbent():void {
// Determine the adsorption direction
// Screen center point
const screenCenterY = Math.round(this.screenWidth / 2);
// left Maximum value
const rightScope = this.screenWidth - this.elementWidth;
// Determine the adsorption direction according to the center point
if (this.elementX < screenCenterY) {
this.animate(0 - (this.hideOffset), 10);
} else {
this.animate(rightScope + (this.hideOffset), 10); }}}Copy the code
Development and debugging
In the process of component development, it is often necessary to debug the function of the component and show the style. At this time, we can use the webpack-dev-server plug-in, which provides us with a basic Web server and has the function of updating the page in real time.
Webpack – dev – server installation
npm install --save-dev webpack-dev-server
Copy the code
! This is just to install it first, and we will configure it for use in the configuration file later
Create a new Drag page and its TS and SCSS files in the Pages folder to debug the component:
The Drag page contents are:
// Drag.html
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Drag</title>
</head>
<body>
<h2>
Drag.html
</h2>
</body>
</html>
Copy the code
// Drag.scss* {margin: 0;
padding: 0;
}
body{
padding: 20px;
}
#drag{
width: 50px;
height: 50px;
background-color: rgb(238.238.238);
border-radius: 50%;
border: 5px solid rgb(170.170.170);
}
p{
height: 50px;
}
Copy the code
//Drag.ts
import './Drag.scss';
import Drag from '.. /.. /components/better-draggable-ball/index';
const dragDom = document.createElement('div');
dragDom.setAttribute('id'.'drag');
const body = document.getElementsByTagName('body') [0];
body.appendChild(dragDom);
new Drag(dragDom, {
defaultPosition: { x: 10.y: 10 },
autoAdsorbent: true});Copy the code
Make a copy of the webpack.config.ts file in the root directory of the project and name it webpack.config.dev.ts.
To modify the webpack.config.dev.ts file:
In terms of configuration types, we need to make some changes. Originally we used the config type in the webpack configuration object module, but now we need to use another module (webpack-dev-server) to configure the devServer property in the configuration object. The config in Webpack does not have the attribute of devServer type, so we define a Configuration interface as the type of Configuration file and let it inherit the Config in webpack. When it under devServer WebpackDevServerConfiguration correspond
// webpack.config.dev.ts
import { Configuration as webpackConfiguration } from 'webpack';
import {Configuration as WebpackDevServerConfiguration} from 'webpack-dev-server';
interface Configuration extendswebpackConfiguration{ devServer ? : WebpackDevServerConfiguration; }Copy the code
Add devServer attribute and configure the running directory and service interface. Compress refers to whether the code is GZIP compressed:
const config: Configuration = {
// Ignore some code
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true.port: 9000,}}Copy the code
Add a Drag page to the Entry and plugins properties
// webpack.config.dev.ts
entry: {
// Ignore some code
Drag: './src/pages/Drag/Drag.ts'./ / Drag page
},
Copy the code
// webpack.config.dev.ts
new HtmlWebpackPlugin({
title: 'Drag'.filename: 'Drag.html'.template: './src/pages/Drag/Drag.html'.chunks: ['Drag'.'main'],}).Copy the code
Modify package.json file:
The config parameter specifies the configuration file. If not, the default is the webpack.config.ts file
The open parameter automatically opens the target URL when the service is started
"scripts": {
"... Some commands are ignored here... "
"serve": "webpack serve --config webpack.dev.config.ts --open"
},
Copy the code
In order to facilitate everyone CVCVCV method, I directly put the whole webpack.config.dev.ts paste up haha, lazy programmer is the first productivity.
// webpack.config.dev.ts
import * as path from 'path';
import { Configuration as webpackConfiguration } from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ESLintPlugin from 'eslint-webpack-plugin';
import {Configuration as WebpackDevServerConfiguration} from 'webpack-dev-server';
interface Configuration extendswebpackConfiguration{ devServer ? : WebpackDevServerConfiguration; }const config: Configuration = {
mode: 'production'.entry: {
main: './src/main.ts'.index: './src/pages/index/index.ts'./ / the index page
Drag: './src/pages/Drag/Drag.ts'./ / hello page
'better-draggable-ball': './src/components/better-draggable-ball/index.ts'./ / better - draggable - ball plug-in
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: (pathData:any) = > (pathData.chunk.name === 'better-draggable-ball' ? 'js/components/[name]/[name].js' : 'js/[name]/[name].js'),
clean: true,},devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true.port: 9000,},resolve: {
extensions: ['.tsx'.'.ts'.'.js'],},module: {
rules: [{test: /\.s[ac]ss$/i,
use: [
// Generate JS strings as style nodes
'style-loader'.// Convert CSS to CommonJS modules
'css-loader'.// Compile Sass to CSS
'sass-loader',]}, {test: /\.css$/i,
use: ['style-loader'.'css-loader'],}, {test: /\.(png|svg|jpg|jpeg|gif)$/i.type: 'asset/resource'}, {test: /\.(woff|woff2|eot|ttf|otf)$/i.type: 'asset/resource'}, {test: /\.tsx? $/,
use: 'ts-loader'.exclude: /node_modules/,}]},plugins: [
new HtmlWebpackPlugin({
title: 'index'.filename: 'index.html'.template: './src/pages/index/index.html'.chunks: ['index'.'main'],}).new HtmlWebpackPlugin({
title: 'Drag'.filename: 'Drag.html'.template: './src/pages/Drag/Drag.html'.chunks: ['Drag'.'main'],}).new ESLintPlugin({
extensions: ['js'.'ts'].exclude: '/node_modules/',})]};export default config;
Copy the code
After NPM run serve is executed, webserver will start to run and build a service environment, and the corresponding URL address will also be displayed in terminal. Webserver will also automatically open the browser for us to access the corresponding URL address.
When this is not the Drag page we want, there are now two ways to switch to the Drag page:
-
In the browser to the URL path is modified to http://localhost:8080/Drag.html
- This is not recommended; you need to manually modify the service every time you start it
-
In the DevServer object, add the openPage property so that the page is displayed automatically
-
devServer: { openPage: 'Drag.html',}Copy the code
-
Running again, the browser automatically opens the Drag page and our better-drag-Ball component is displayed.
The last
At this point, the debug environment for our component has been deployed.
Thank you for watching. In the next article, we’ll package this component in a multi-version output package that lets users use it directly by referencing javascript files.
😀😀 follow me and don’t get lost! 😀 😀