Vue3框架搭建 vue框架搭建步骤
connygpt 2024-10-11 11:57 9 浏览
目录
- 二十一、项目搭建规范1、创建项目2、代码规范a、.editorconfig(编辑器编辑风格)b、prettier(代码格式化风格)c、eslint(代码风格检测工具)d、git Husky(提交前代码格式化风格)e、commitizen(提交信息格式化风格)f、commitlint(提交信息风格检测工具)3、项目结构a、vue.config.jsb、vue-routerc、vuexd、element-pluse、axiosf、环境变量g、tsconfig.jsonh、shims-vue.d.ts
- 二十二、项目实战细节(一)1、获取组件实例的类型2、确定props的类型3、setup顶层编写方式中的props用法4、浏览器的重绘和重排(回流)5、echarts使用canvas或者svg渲染6、setup顶层编写方式中子组件暴露属性和方法的用法
- 二十三、项目打包和自动化部署1、centos7安装dnf2、dnf方式安装java3、安装jenkins4、dnf方式安装nginx5、dnf方式安装git6、jenkins配置与使用
二十一、项目搭建规范
1、创建项目
- 命令
vue create vue3-ts
- 选项
? Please pick a preset:
- Manually select features
? Check the features needed for your project:
- Choose Vue version, Babel, TS, Router, Vuex, CSS Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with
- 3.x
? Use class-style component syntax?
- No
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)?
- Yes
? Use history mode for router? (Requires proper server setup for index fallback in production)
- No
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
- Sass/SCSS (with dart-sass)
? Pick a linter / formatter config:
- Prettier
? Pick additional lint features:
- Lint on save
? Where do you prefer placing config for Babel, ESLint, etc.?
- In dedicated config files
? Save this as a preset for future projects?
- No
? Pick the package manager to use when installing dependencies:
- NPM
2、代码规范
a、.editorconfig(编辑器编辑风格)
# http://editorconfig.org
root = true
[*] # 表示所有文件适用
charset = utf-8 # 设置文件字符集为 utf-8
indent_style = space # 缩进风格(tab | space)
indent_size = 2 # 缩进大小
end_of_line = lf # 控制换行类型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行首的任意空白字符
insert_final_newline = true # 始终在文件末尾插入一个新行
[*.md] # 表示仅 md 文件适用以下规则
max_line_length = off
trim_trailing_whitespace = false
b、prettier(代码格式化风格)
- 安装
npm i -D prettier
- .prettierrc
{
"useTabs": false,
"tabWidth": 2,
"printWidth": 80,
"singleQuote": true,
"trailingComma": "none",
"semi": false
}
* useTabs:使用tab缩进还是空格缩进,选择false
* tabWidth:tab是空格的情况下,是几个空格,选择2个
* printWidth:当行字符的长度,推荐80,也有人喜欢100或者120
* singleQuote:使用单引号还是双引号,选择true,使用单引号
* trailingComma:在多行输入的尾逗号是否添加,设置为 `none`
* semi:语句末尾是否要加分号,默认值true,选择false表示不加
- .prettierignore
/dist/*
.local
.output.js
/node_modules/**
**/*.svg
**/*.sh
/public/*
- package.json
{
"scripts": {
"prettier": "prettier --write ."
}
}
c、eslint(代码风格检测工具)
- 安装
npm i -D eslint-plugin-prettier eslint-config-prettier
- .eslintrc.js
module.exports = {
root: true,
env: {
node: true
},
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/typescript/recommended',
'@vue/prettier',
'@vue/prettier/@typescript-eslint',
// 解决eslint和prettier的冲突
'plugin:prettier/recommended'
],
parserOptions: {
ecmaVersion: 2020
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'@typescript-eslint/no-var-requires': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-non-null-assertion': 'off'
}
}
d、git Husky(提交前代码格式化风格)
- 命令
################
# 1、用于拦截git命令
# 2、项目三处变化:
# - package.json多一个依赖({"devDependencies": {"husky": ""}})
# - 项目下多一个.husky目录
# - package.json多一个脚本({"scripts": {"prepare": "husky install"}})
################
npx husky-init && npm install
- .husky/pre-commit
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
e、commitizen(提交信息格式化风格)
- 安装
npm i -D commitizen
- 命令
################
# 1、项目两处变化:
# - package.json多一个依赖({"devDependencies": {"cz-conventional-changelog": ""}})
# - package.json多一个配置
# ({"config": {"commitizen": {"path": "./node_modules/cz-conventional-changelog"}}})
################
npx commitizen init cz-conventional-changelog --save-dev --save-exact
- package.json(代码的git提交操作使用此脚本)
{
"scripts": {
"commit": "cz"
}
}
- 选项
? Select the type of change that you're committing:
- 提交的类型
? What is the scope of this change (e.g. component or file name): (press enter to skip)
- 提交的范围
? Write a short, imperative tense description of the change (max 87 chars):
- 提交的简短描述信息
? Provide a longer description of the change: (press enter to skip)
- 提交的详细描述信息
? Are there any breaking changes?
- No
? Does this change affect any open issues?
- No
提交的类型 | 作用 |
feat | 新增特性 (feature) |
fix | 修复 Bug(bug fix) |
docs | 修改文档 (documentation) |
style | 代码格式修改(white-space, formatting, missing semi colons, etc) |
refactor | 代码重构(refactor) |
perf | 改善性能(A code change that improves performance) |
test | 测试(when adding missing tests) |
build | 变更项目构建或外部依赖(例如 scopes: webpack、gulp、npm 等) |
ci | 更改持续集成软件的配置文件和 package 中的 scripts 命令,例如 scopes: Travis, Circle 等 |
chore | 变更构建流程或辅助工具(比如更改测试环境) |
revert | 代码回退 |
f、commitlint(提交信息风格检测工具)
- 安装
npm i -D @commitlint/config-conventional @commitlint/cli
- commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional']
}
- 命令
################
# 1、项目一处变化:
# - .husky下多一个commit-msg文件
################
npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"
3、项目结构
a、vue.config.js
const path = require('path')
module.exports = {
// 1、方式一: 通过Vue CLI提供的选项来配置(推荐)
outputDir: 'dist',
publicPath: '/',
// 2、方式二: 通过configureWebpack(与webpack配置选项一致)
// 2.1、对象:合并webpack配置
configureWebpack: {
resolve: {
alias: {
components: '@/components'
}
}
},
// 2.2、函数:修改webpack配置
/*
configureWebpack: (config) => {
config.resolve.alias = {
'@': path.resolve(__dirname, 'src'),
components: '@/components'
}
},*/
// 3、方式三:通过chainWebpack(与webpack配置选项一致)
// 3.1、函数:修改webpack配置
/*
chainWebpack: (config) => {
config.resolve.alias
.set('@', path.resolve(__dirname, 'src'))
.set('components', '@/components')
}*/
}
b、vue-router
- 安装
npm i -S vue-router@next
- src/router/index.ts
import { createRouter, createWebHashHistory } from 'vue-router'
import type { RouteRecordRaw } from 'vue-router'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
component: () => import('../views/Home.vue')
},
{
path: '/about',
component: () => import('../views/About.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
- src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
- src/App.vue
<template>
<div>
<router-link to="/home">Home</router-link>
<router-link to="/about">About</router-link>
</div>
<router-view />
</template>
c、vuex
- 安装
npm i -S vuex@next
- src/store/index.ts
import { createStore, useStore as useVuexStore } from 'vuex'
import user, { IUserState } from './modules/user'
export interface IRootState {
user: IUserState
}
export default createStore<IRootState>({
modules: {
user
}
})
export function useStore() {
return useVuexStore<IRootState>()
}
- src/store/modules/user.ts
import { IRootState } from '@/store'
export interface IUserState {
token: string
userInfo: {
id: string
nickname: string
}
}
const user: Module<IUserState, IRootState> = {
namespaced: true,
state() {
return {
token: '',
userInfo: {
id: '',
nickname: ''
}
}
},
mutations: {},
actions: {}
}
export default user
- src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
const app = createApp(App)
app.use(store)
app.mount('#app')
- src/App.vue
<template>
<div></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useStore } from '@/store'
export default defineComponent({
setup() {
const store = useStore()
console.log(store.state.user.token)
return {}
}
})
</script>
<style lang="scss" scoped></style>
d、element-plus
- 安装
npm i -S element-plus
- src/main.ts
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(ElementPlus)
app.mount('#app')
- src/App.vue
<template>
<el-button type="primary">黄婷婷</el-button>
</template>
e、axios
- 安装
npm i -S axios
- 知识点
* Promise<any>指定了泛型,则resolve(res)和.then(res=>{})的res就是any类型
* axios配置默认值优先级:请求的config参数 > 实例的defaults属性
* axios实例多个拦截器会合并,执行顺序是从后往前
- src/utils/request.ts
import axios from 'axios'
import type { AxiosRequestConfig } from 'axios'
import Cookies from 'js-cookie'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 5000
})
service.interceptors.request.use(
(config) => {
// 1、请求头添加令牌
const token = Cookies.get('token')
if (token && config.headers) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error) => {
return Promise.reject(error)
}
)
service.interceptors.response.use(
(response) => {
// 2、处理后端接口统一响应结果的状态码
switch (response.data.code) {
case 999:
console.log('错误')
break
default:
}
return response
},
(error) => {
// 3、处理http的状态码
switch (error.response.status) {
case 401:
console.log('未认证或令牌过期')
break
case 403:
console.log('无权限访问拒绝')
break
default:
}
return Promise.reject(error)
}
)
interface IResponseBody<T = any> {
code: number
data: T
message: string
}
export default function <T = any>(
config: AxiosRequestConfig
): Promise<IResponseBody<T>> {
return service(config).then((res) => {
return res.data
})
}
- src/api/user.ts
import request from '@/utils/request'
export function login(data: any) {
return request({
url: '/user/login',
method: 'post',
data
})
}
- src/App.vue
<template>
<div></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { login } from '@/api/user'
export default defineComponent({
setup() {
login({}).then((res) => {
console.log(res)
})
return {}
}
})
</script>
<style lang="scss"></style>
f、环境变量
* 模式:
- 脚本命令:vue-cli-service serve(默认--mode development)
引用文件:.env.development
NODE_ENV:process.env.NODE_ENV = "development"
- 脚本命令:vue-cli-service build(默认--mode production)
引用文件:.env.production
NODE_ENV:process.env.NODE_ENV = "production"
- 脚本命令:vue-cli-service build --mode staging(手动指定)
引用文件:.env.staging
NODE_ENV:process.env.NODE_ENV = "staging"
* NODE_ENV变量无需手动赋值
* 其他变量应以VUE_APP_开头才会自动注入到代码中
* .env优先级小于.env.development或.env.production等
g、tsconfig.json
{
"compilerOptions": {
// 目标代码:babel编译(esnext),tsc编译(es5)
"target": "esnext",
// 目标代码模块化方案:es模块化方案(esnext),模块化方案混合使用(umd)
"module": "esnext",
// ts严格模式
"strict": true,
// jsx处理:不转化处理(preserve)
"jsx": "preserve",
// 导入功能辅助
"importHelpers": true,
// 解析模块方式:后缀名顺序查找文件(node)
"moduleResolution": "node",
// 跳过第三方库的类型检测
"skipLibCheck": true,
// 源代码模块化方案:模块化方案混合使用
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
// 是否生成映射文件
"sourceMap": true,
// 文件解析路径
"baseUrl": ".",
// 解析类型
"types": [
"webpack-env"
],
// 路径别名(与webpack配置对应)
"paths": {
"@/*": [
"src/*"
]
},
// 基础类型库
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"src/**/*.vue",
"tests/**/*.ts",
"tests/**/*.tsx"
],
"exclude": [
"node_modules"
]
}
h、shims-vue.d.ts
/* eslint-disable */
/**
* 1、声明.vue文件:.vue文件导出的component对象的类型是DefineComponent<{}, {}, any>
* 2、.vue文件defineComponent函数:
* - 源码:function defineComponent(options) {return options}
* - 作用:可以使options具有类型限制
*/
declare module '*.vue' {
import type { DefineComponent } from 'vue'
const component: DefineComponent<{}, {}, any>
export default component
}
二十二、项目实战细节(一)
1、获取组件实例的类型
- 父组件
<template>
<div>
<son-component ref="sonComponentRef"></son-component>
<el-button @click="clickHandler">减1按钮</el-button>
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
import SonComponent from './son-component.vue'
export default defineComponent({
components: { SonComponent },
setup() {
const sonComponentRef = ref()
type SonComponentType = InstanceType<typeof SonComponent>
const clickHandler = () => {
/**
* 1、函数签名以new关键字为前缀:
* - var BankAccount: new() => BankAccount;
* 则BankAccount函数只能以new BankAccount()方式调用
* 2、InstanceType获取构造函数的实例类型:
* - InstanceType<typeof SonComponent>;
* 获取子组件实例的类型
*/
const sonComponentInstance: SonComponentType = sonComponentRef.value
// 3、组件实例中的属性并不是ref对象,而是proxy对象,所以不需要.value
sonComponentInstance.person.age--
}
return {
sonComponentRef,
clickHandler
}
}
})
</script>
- 子组件
<template>
<div>{{ person }}</div>
<el-button @click="clickHandler">加1按钮</el-button>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue'
export default defineComponent({
setup() {
const person = ref({
name: '黄婷婷',
age: 18
})
const clickHandler = () => {
person.value.age++
}
return {
person,
clickHandler
}
}
})
</script>
2、确定props的类型
<template>
<div></div>
</template>
<script lang="ts">
import { defineComponent, PropType } from 'vue'
interface IPerson {
username: string
age: number
}
export default defineComponent({
props: {
persons: {
type: Array as PropType<IPerson[]>,
required: true
}
},
setup(props) {
props.persons.forEach((item) => {
console.log(item.username)
})
return {}
}
})
</script>
<style lang="scss" scoped></style>
3、setup顶层编写方式中的props用法
<template>
<div ref="echartsDivRef" :style="{ width: width, height: height }"></div>
</template>
<script lang="ts" setup>
import * as echarts from 'echarts'
import { EChartsOption } from 'echarts'
import { ref, onMounted, withDefaults, defineProps } from 'vue'
const props = withDefaults(
defineProps<{
options: EChartsOption // required: true
width?: string
height?: string
}>(),
{
width: '100%', // defaults: '100%'
height: '100%'
}
)
const echartsDivRef = ref<HTMLDivElement>()
onMounted(() => {
const echartsInstance = echarts.init(echartsDivRef.value!, 'light', {
renderer: 'svg'
})
echartsInstance.setOption(props.options)
})
</script>
4、浏览器的重绘和重排(回流)
* 重绘和回流:
- 重绘:比如颜色的改变,不会影响后续节点
- 回流:比如布局的改变,会影响后续节点,影响性能的关键因素
* css优化:
- transform替代position
- 避免使用table布局
- visibility: hidden替代display: none
- 样式尽可能设置在DOM树的末端,限制回流的范围,减少影响的节点
- 避免使用包含选择器(div > span)和css表达式(calc())
* js优化:
- 避免频繁操作DOM(虚拟节点)
- 避免频繁读取会引发回流的属性(offset)
5、echarts使用canvas或者svg渲染
* canvas:大数据量的图表、视觉特效
* svg(推荐):内存占用低、浏览器缩放不会模糊(矢量图)
6、setup顶层编写方式中子组件暴露属性和方法的用法
<template>
<div></div>
</template>
<script lang="ts" setup>
import { defineExpose, ref } from 'vue'
const person = ref({ name: '黄婷婷', age: 18 })
const clickHnadler = () => {
console.log('黄婷婷')
}
// 父组件ref方式调用子组件方法和获取子组件属性
defineExpose({
person,
clickHnadler
})
</script>
二十三、项目打包和自动化部署
1、centos7安装dnf
yum install epel-release -y
yum install dnf -y
# 查看是否安装成功
dnf
2、dnf方式安装java
dnf search java-1.8
dnf install java-1.8.0-openjdk.x86_64 -y
# 查看是否安装成功
java
3、安装jenkins
- dnf方式安装jenkins(失败)
cd /etc/yum.repos.d/
wget http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
vi jenkins.repo
# baseurl=http://pkg.jenkins.io/redhat,保存退出
dnf install jenkins -y
- rpm方式安装jenkins
# https://mirrors.tuna.tsinghua.edu.cn/jenkins/redhat/:清华大学开源软件镜像站,下载jenkins软件包
dnf install daemonize -y
rpm -ivh jenkins-2.332-1.1.noarch.rpm
- 启动服务
# 启动服务(默认端口号8080)
systemctl start jenkins
# 查看状态
systemctl status jenkins
# 开机自启
systemctl enable jenkins
4、dnf方式安装nginx
- 安装
dnf install nginx -y
- 启动服务
# 启动服务(默认端口80)
# index页面目录:/usr/share/nginx/html/
# nginx配置文件:vi /etc/nginx/nginx.conf
systemctl start nginx
# 查看状态
systemctl status nginx
# 开机自启
systemctl enable nginx
5、dnf方式安装git
dnf install git -y
6、jenkins配置与使用
- jenkins初始化
* 按提示输入密码
* 安装推荐的插件
- jenkins安装nodejs插件
* 系统管理 ->
插件管理 ->
可选插件 ->
搜索nodejs并选择 ->
download now and install after restart ->
安装完成后重启jenkins(空闲时)
* 系统管理 ->
全局工具配置 ->
nodejs安装 ->
设置别名选择版本(自动安装应是选中状态) ->
保存
- jenkins配置用户
# 默认用户是jenkins,访问一些文件会有权限问题
vi /etc/sysconfig/jenkins
# 设置JENKINS_USER="root"
# 重启jenkins
systemctl restart jenkins
- jenkins任务
* 新建任务 ->
输入任务名 ->
构建一个自由风格的软件项目 ->
确定
* 描述
* 源码管理 ->
git ->
仓库URL ->
添加凭证 ->
指定分支
* 构建触发器(手动则跳过此步) ->
定时构建
* 构建环境 ->
Provide Node & npm bin/ folder to PATH
* 构建 ->
执行shell
* 保存
- shell
# shell
pwd
node -v
npm -v
npm install
npm run build
pwd
echo '构建成功'
ls
rm -rf /usr/share/nginx/html/*
cp -rf ./dist/* /usr/share/nginx/html/
- 定时构建的触发器规则
#每半小时构建一次OR每半小时检查一次远程代码分支,有更新则构建
H/30 * * * *
#每两小时构建一次OR每两小时检查一次远程代码分支,有更新则构建
H H/2 * * *
#每天凌晨两点定时构建
H 2 * * *
#每月15号执行构建
H H 15 * *
#工作日,上午9点整执行
H 9 * * 1-5
#每周1,3,5,从8:30开始,截止19:30,每4小时30分构建一次
H/30 8-20/4 * * 1,3,5
相关推荐
- 3分钟让你的项目支持AI问答模块,完全开源!
-
hello,大家好,我是徐小夕。之前和大家分享了很多可视化,零代码和前端工程化的最佳实践,今天继续分享一下最近开源的Next-Admin的最新更新。最近对这个项目做了一些优化,并集成了大家比较关注...
- 干货|程序员的副业挂,12个平台分享
-
1、D2adminD2Admin是一个完全开源免费的企业中后台产品前端集成方案,使用最新的前端技术栈,小于60kb的本地首屏js加载,已经做好大部分项目前期准备工作,并且带有大量示例代码,助...
- Github标星超200K,这10个可视化面板你知道几个
-
在Github上有很多开源免费的后台控制面板可以选择,但是哪些才是最好、最受欢迎的可视化控制面板呢?今天就和大家推荐Github上10个好看又流行的可视化面板:1.AdminLTEAdminLTE是...
- 开箱即用的炫酷中后台前端开源框架第二篇
-
#头条创作挑战赛#1、SoybeanAdmin(1)介绍:SoybeanAdmin是一个基于Vue3、Vite3、TypeScript、NaiveUI、Pinia和UnoCSS的清新优...
- 搭建React+AntDeign的开发环境和框架
-
搭建React+AntDeign的开发环境和框架随着前端技术的不断发展,React和AntDesign已经成为越来越多Web应用程序的首选开发框架。React是一个用于构建用户界面的JavaScrip...
- 基于.NET 5实现的开源通用权限管理平台
-
??大家好,我是为广大程序员兄弟操碎了心的小编,每天推荐一个小工具/源码,装满你的收藏夹,每天分享一个小技巧,让你轻松节省开发效率,实现不加班不熬夜不掉头发,是我的目标!??今天小编推荐一款基于.NE...
- StreamPark - 大数据流计算引擎
-
使用Docker完成StreamPark的部署??1.基于h2和docker-compose进行StreamPark部署wgethttps://raw.githubusercontent.com/a...
- 教你使用UmiJS框架开发React
-
1、什么是Umi.js?umi,中文可发音为乌米,是一个可插拔的企业级react应用框架。你可以将它简单地理解为一个专注性能的类next.js前端框架,并通过约定、自动生成和解析代码等方式来辅助...
- 简单在线流程图工具在用例设计中的运用
-
敏捷模式下,测试团队的用例逐渐简化以适应快速的发版节奏,大家很早就开始运用思维导图工具比如xmind来编写测试方法、测试点。如今不少已经不少利用开源的思维导图组件(如百度脑图...)来构建测试测试...
- 【开源分享】神奇的大数据实时平台框架,让Flink&Spark开发更简单
-
这是一个神奇的框架,让Flink|Spark开发更简单,一站式大数据实时平台!他就是StreamX!什么是StreamX大数据技术如今发展的如火如荼,已经呈现百花齐放欣欣向荣的景象,实时处理流域...
- 聊聊规则引擎的调研及实现全过程
-
摘要本期主要以规则引擎业务实现为例,陈述在陌生业务前如何进行业务深入、调研、技术选型、设计及实现全过程分析,如果你对规则引擎不感冒、也可以从中了解一些抽象实现过程。诉求从硬件采集到的数据提供的形式多种...
- 【开源推荐】Diboot 2.0.5 发布,自动化开发助理
-
一、前言Diboot2.0.5版本已于近日发布,在此次发布中,我们新增了file-starter组件,完善了iam-starter组件,对core核心进行了相关优化,让devtools也支持对IAM...
- 微软推出Copilot Actions,使用人工智能自动执行重复性任务
-
IT之家11月19日消息,微软在今天举办的Ignite大会上宣布了一系列新功能,旨在进一步提升Microsoft365Copilot的智能化水平。其中最引人注目的是Copilot...
- Electron 使用Selenium和WebDriver
-
本节我们来学习如何在Electron下使用Selenium和WebDriver。SeleniumSelenium是ThoughtWorks提供的一个强大的基于浏览器的开源自动化测试工具...
- Quick 'n Easy Web Builder 11.1.0设计和构建功能齐全的网页的工具
-
一个实用而有效的应用程序,能够让您轻松构建、创建和设计个人的HTML网站。Quick'nEasyWebBuilder是一款全面且轻巧的软件,为用户提供了一种简单的方式来创建、编辑...
- 一周热门
- 最近发表
- 标签列表
-
- kubectlsetimage (56)
- mysqlinsertoverwrite (53)
- addcolumn (54)
- helmpackage (54)
- varchar最长多少 (61)
- 类型断言 (53)
- protoc安装 (56)
- jdk20安装教程 (60)
- rpm2cpio (52)
- 控制台打印 (63)
- 401unauthorized (51)
- vuexstore (68)
- druiddatasource (60)
- 企业微信开发文档 (51)
- rendertexture (51)
- speedphp (52)
- gitcommit-am (68)
- bashecho (64)
- str_to_date函数 (58)
- yum下载包及依赖到本地 (72)
- jstree中文api文档 (59)
- mvnw文件 (58)
- rancher安装 (63)
- nginx开机自启 (53)
- .netcore教程 (53)