module.exports = { entry: 'https://www.jb51.net/article/main.js', mode: 'development', devServer: { contentBase: './dist', }, module: { rules: [ { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'], plugins: [['@babel/plugin-transform-react-jsx', { pragma: 'createElement' }]], }, }, }, ], }, };
用过 Vue 或者 React 的同学都知道,启动一个本地调试环境服务器,只需要执行 npm 命令就可以了。这里我们也设置一个快捷启动命令。打开我们的 package.json,在 scripts 的配置中添加一行 "start": "webpack start" 即可。
{ "name": "jsx-component", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "webpack serve" }, "author": "", "license": "ISC", "devDependencies": { "@babel/core": "^7.12.3", "@babel/plugin-transform-react-jsx": "^7.12.5", "@babel/preset-env": "^7.12.1", "babel-loader": "^8.1.0", "webpack": "^5.4.0", "webpack-cli": "^4.2.0", "webpack-dev-server": "^3.11.0" }, "dependencies": {} }
这样我们就可以直接执行下面这个命令启动我们的本地调试服务器啦!
npm start
开启了这个之后,当我们修改任何文件时都会被监听到,这样就会实时给我们打包文件,非常方便我们调试。看到上图里面表示,我们的实时本地服务器地址就是 :8080。我们在浏览器直接打开这个地址就可以访问这个项目。
这里要注意的一个点,我们把运行的目录改为了 dist,因为我们之前的 main.html 是放在根目录的,这样我们就在 localhost:8080 上就找不到这个 HTML 文件了,所以我们需要把 main.html 移动到 dist 目录下,并且改一下 main.js 的引入路径。
<!-- main.html 代码 --> <body></body> <script src="https://www.jb51.net/article/main.js"></script>
打开链接后我们发现 Carousel 组件已经被挂載成功了,这个证明我们的代码封装是没有问题的。
接下来我们继续来实现我们的轮播图功能,首先要把我们的图片数据传进去我们的 Carousel 组件里面。
let a = <Carousel src=https://www.jb51.net/{gallery}/>;
这样我们的 gallery 数组就会被设置到我们的 src 属性上。但是我们的这个 src 属性不是给我们的 Carousel 自身的元素使用的。也就说我们不是像之前那样直接挂載到 this.root 上。
所以我们需要另外储存这个 src 上的数据,后面使用它来生成我们轮播图的图片展示元素。在 React 里面是用 props 来储存元素属性,但是这里我们就用一个更加接近属性意思的 attributes 来储存。
因为我们需要储存进来的属性到 this.attributes 这个变量中,所以我们需要在 Component 类的 constructor 中先初始化这个类属性。
然后这个 attributes 是需要我们另外存储到类属性中,而不是挂載到我们元素节点上。所以我们需要在组件类中重新定义我们的 setAttribute 方法。
我们需要在组件渲染之前能拿到 src 属性的值,所以我们需要把 render 的触发放在 mountTo 之内。
class Carousel extends Component { // 构造函数 // 创建 DOM 节点 constructor() { super(); this.attributes = Object.create(null); } setAttribute(name, value) { this.attributes[name] = value; } render() { console.log(this.attributes); return document.createElement('div'); } mountTo() { parent.appendChild(this.render()); } }
接下来我们看看实际运行的结果,看看是不是能够获得图片的数据。
接下来我们就去把这些图给显示出来。这里我们需要改造一下 render 方法,在这里加入渲染图片的逻辑:
首先我们需要把创建的新元素储起来
循环我们的图片数据,给每条数据创建一个 img 元素
给每一个 img 元素附上 src = 图片 url
把附上 src 属性的图片元素挂載到我们的组件元素 this.root 上
最后让 render 方法返回 this.root
class Carousel extends Component { // 构造函数 // 创建 DOM 节点 constructor() { super(); this.attributes = Object.create(null); } setAttribute(name, value) { this.attributes[name] = value; } render() { this.root = document.createElement('div'); for (let picture of this.attributes.src) { let child = document.createElement('img'); child.src = picture; this.root.appendChild(child); } return this.root; } mountTo(parent) { parent.appendChild(this.render()); } }
就这样我们就可以看到我们的图片被正确的显示在我们的页面上。
排版与动画