Element表单校验怎么实现,有哪些要点
Admin 2022-06-08 群英技术资讯 632 次浏览
Element-ui表单校验规则,使得错误提示可以直接在form-item下面显示,无需弹出框,因此还是很好用的。
我在做了登录页面的表单校验后,一度以为我已经很了解表单的校验规则。但我在深入使用表单校验规则时,遇到下列问题:
上述问题,让我感觉几乎成了小白。于是迫使我从头开始研究校验规则,查阅相关文档。
本文分享一下对于表单校验规则的心得体会。
作为规则校验的入门,以登录页面为例,代码如下:
<template> <div class="login-container"> <el-form ref="form" :model="form" :rules="rules" label-width="80px" class="login-form"> <h2 class="login-title">XX管理系统登录</h2> <el-form-item label="用户名:" prop="username"> <el-input v-model="form.username"></el-input> </el-form-item> <el-form-item label="密 码:" prop="password"> <el-input v-model="form.password" type="password"></el-input> </el-form-item> <el-form-item label="验证码:" prop="verifyCode"> <el-input v-model="form.verifyCode"></el-input> <div class="divVerifyCodeImg" @click="getVerifyCode(true)"> <img id="verifyCodeImg" style="height:40px; width: 100px; cursor: pointer;" alt="点击更换" title="点击更换" /> </div> </el-form-item> <el-form-item> <el-button type="primary" id="login" style="width:160px" @click="submitForm('form')">登录</el-button> </el-form-item> </el-form> </div> </template> <script> import { mapMutations } from 'vuex' export default { data() { return { form: { username: "", password: "", verifyCode: "", }, rules: { username: [ {required: true, message: "用户名不能为空", trigger: 'blur'}, ], password: [ {required: true, message: "密码不能为空", trigger: 'blur'}, {min: 6, max: 30, message: "密码6-30位", trigger: 'blur'} ], verifyCode: [ {required: true, message: "验证码不能为空", trigger: 'blur'}, ] } }; }, methods: { // 提交登录 submitForm(formName) { let _this = this; // 执行校验 this.$refs[formName].validate(valid => { // 验证通过为true,有一个不通过就是false if (valid) { // 通过校验 // 登录处理 // .... } else { // 没通过校验 console.log('验证失败'); return false; } }); }, } } </script>
form项,指明使用校验规则:
<el-form ref="form" :model="form" :rules="rules" label-width="80px" class="login-form">
:rules="rules" 指明了校验规则使用rules规则对象,你也可以使用其它名称,如rules1。
prop项,指明哪些字段可能使用校验规则:
<el-form-item label="用户名:" prop="username"> <el-input v-model="form.username"></el-input> </el-form-item>
如果prop项指定的属性值,如username,在rules中也有相应的项,则表示该属性值执行规则校验。这个属性必须是form的model属性绑定的数据对象的属性,本例中为form,其在data中定义:
form: { username: "", password: "", verifyCode: "", },
rules项,即校验规则集,其在data中定义,其名称必须与form的:rules属性绑定的rules规则对象名一致。
rules: { username: [ {required: true, message: "用户名不能为空", trigger: 'blur'}, ], password: [ {required: true, message: "密码不能为空", trigger: 'blur'}, {min: 6, max: 30, message: "密码6-30位", trigger: 'blur'} ], verifyCode: [ {required: true, message: "验证码不能为空", trigger: 'blur'}, ] }
这是一个对象,每个元素的类型为:{属性名:[rule]},属性名对于prop的属性值。[rule]是一个规则数组,规则数组的每一项是一条对本属性的校验规则。
rule项,即规则数组的元素,这是本文要重点探讨的项目。这里先就上述rules的各元素项解析一下:
有了这些解释,不难理解上述rules定义的各属性的校验规则。
this.$refs[‘form'].validate(valid => { // 验证通过为true,有一个不通过就是false if (valid) { // 通过校验 } else { // 没通过校验 } });
这个validate方法,要求所有校验规则都通过,才放行。其中,$refs[‘form'],指向form的ref属性值。
规则校验的核心为为async-validator插件,官网:https://github.com/yiminghe/async-validator。
Element-UI使用了该插件,并进行了封装。官网:https://element.eleme.cn/#/zh-CN/component/form。
因此两边的资料都会有帮助。
有时候,prop不是一个简单的属性,而是包在其它对象下的属性。如:
<el-form-item label="登 录 名:" prop="formData.loginName"> <el-input v-model="form.formData.loginName" :disabled="form.formData.userId != 0"></el-input> </el-form-item>
form的model绑定的form对象,其形式为:
form:{ // form数据字段,为提交后端方便,建议与UserInfo字段命名一致 formData : { userId : 0, loginName : '', passwd : '', // ... }, // 用户类型选择框当前显示值 userTypeLabel : "", // ... },
此时,rules的元素定义,不能用下列形式:
formData.loginName: [ {required: true, message: "登录名不能为空", trigger: 'blur'}, ],
这样,编译会报错!
应使用下列形式:
'formData.loginName': [ {required: true, message: "登录名不能为空", trigger: 'blur'}, ],
即用单引号或双引号将之包起来,变成一个字符串。
关于自定义校验器validator,网上的相关资料很多,如常用正则检查的validator。
规则定义方法:
'formData.loginName': [ {required: true, message: "登录名不能为空", trigger: 'blur'}, {validator:loginNameValidator, trigger: 'blur'} ],
表示'formData.loginName'属性使用了loginNameValidator的校验器。考虑到代码的复用,一般将自定义的校验器独成了js文件,便于其它页面或项目使用。
在/src/common/目录下,创建validator.js文件,代码如下:
/* 登录名校验 */ export function loginNameValidator(rule, value, callback){ const reg= /^[a-zA-Z][\w-. @]*$/; if(value == '' || value == undefined || value == null){ callback(); }else { if (!reg.test(value)){ callback(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号')); }else { callback(); } } }
在vue文件中导入此validator.js文件:
import {loginNameValidator} from '@/common/validator.js'
如果需导入多个外部校验器,则在{}中包含多个,如{loginNameValidator,passwordValidator}。
这里有个小坑,稍微提一句。
根据目录结构,我先使用下列语句:
import {loginNameValidator} from '../../../common/validator.js'
结果,编译错误,说找不到'../../../common/validator.js'文件,于是各种路径表示方法尝试,均告失败。最后还是使用改用@通过了,因为/bulid/webpack.base.conf.js中配置了alias,指示@表示src目录。
回到自定义validator,其形式为:
function ValidatorFuncName(rule, value, callback)
方法名,随意指定。
实际上,其完整形式为:
function ValidatorFuncName(rule, value, callback, source, options)
参数含义如下:
rule:指向规则的对象,可以在方法代码中,加入第一句:
console.log(rule);
可将rule参数打印出来看,就是本条规则的对象数据。
value:属性的值,该值为需要校验的值。
callback:指向校验结束的回调函数,如果校验通过,调用callback(),如果未通过,一般使用下列形式:
callback(new Error('具体的提示信息'));
或带参数的提示:
return callback(new Error(`${rule.field} must be lowercase alphanumeric characters`));
注意,字符串格式化,不是使用单引号括起来,而是用“~”符号括起来。
也可以使用async-validator官网(https://github.com/yiminghe/async-validator)的方法:
util.format('%s must be lowercase alphanumeric characters', rule.field),
util文件中包含format方法,这个util.ts文件,在官网的src/目录下,这是个ts文件,可以类似做一个公共方法。
实际上,可以返回一个Error的数组,即errors,如:
const errors = []; errors.push(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号')); errors.push(new Error('3444要求为:英文')); return callback(errors);
但从实际效果看,表单只显示了第一行的提示,估计Element的表单不支持显示多行错误信息。
更复杂的校验器,可以携带参数,如:
// 整数范围值校验 export const intRangeValidator = (min, max) => (rule, value, callback) => { var isInRange = (value >= min) && (value <= max); const reg = /^-?\d+$/; var isInt = reg.test(value); if (isInRange && isInt){ return callback(); }else{ return callback(new Error(`要求是在${min}到${max}的整数 [${min}, ${max}]`)); } }
使用方法:
'formData.age': [ {validator: intRangeValidator(1,100), trigger: 'blur'} ],
表示,formData.age属性的取值范围为1-100的整数。
自定义校验器validator提供了自由发挥的空间,可以使用正则匹配、数值计算和比较等运算等,进行复杂的校验,因此比较常用。但用自定义校验器validator,有时会显得过于繁琐。
自定义校验器validator不一定要放置在外部文件中,也可以放置vue文件中。
放置在data中,但不被return所包括的位置,尾部没有逗号。
const loginNameValidator = (rule, value, callback) => { const reg= /^[a-zA-Z][\w-. @]*$/; if(value == '' || value == undefined || value == null){ callback(); }else { if (!reg.test(value)){ callback(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号')); }else { callback(); } } }
或直接在规则中定义:
'formData.loginName': [ {required: true, message: "登录名不能为空", trigger: 'blur'}, {validator(rule, value, callback){ const reg= /^[a-zA-Z][\w-. @]*$/; if(value == '' || value == undefined || value == null){ callback(); }else { if (!reg.test(value)){ callback(new Error('要求为:英文字母开头,后续为字母数字及_-. @符号')); }else { callback(); } } }, trigger: 'blur'} ],
类型type的基本用法如下:
'formData.age': [ {type: 'integer',message: "值要求为整数",trigger: 'blur'}, ],
类型也是一个规则项,如不符合类型要求,则提示错误信息。
规则支持的类型如下:
这里的url和email类型,可以直接用于相关含义的属性校验,如:
'formData.email': [ {type: 'email', message: "必须符合邮箱地址格式",trigger: 'blur'} ],
日期类型也比较有用,这些内置类型,使得我们可以不必通过自定义校验器validator来处理。
对于数值类型(number,integer,float)以及boolean型,由于input输入的都为字符串,因此必须进行类型转换,否则校验通不过。这里涉及到transform的用法。
transform是一个钩子函数,在开始验证之前可以对数据先处理后验证。如下面示例:
'formData.age': [ { type: 'integer', message: "值要求为整数", trigger: 'blur', transform(value){return parseInt(value);}, }, ],
经过transform类型转化后,formData.age属性的校验规则就能正常使用了,否则总是通不过类型校验。(这里实际上有点问题,如允许输出12ab这种形式的值,parseInt得到值为12)
对于类型转换,transform还有更简洁而严格的表述:
'formData.age': [ { type:'integer', message: "值要求为整数", trigger: 'blur', transform:Number}, }, ],
表示转换为数字类型,这样就行了。值为1.2或12ab都不能通过校验。
transform除了类型转换外,还可以进行其它处理,如:
'formData.age': [ {type : 'string',pattern:/1/,message: "值要求为1-100的数",transform(value){return parseInt(value)>=1 && parseInt(value)<=100 ? "1" : "0";},} ],
等于某个值:
'formData.age': [ {type : 'string',pattern:/1/,message: "值要求必须为50",transform(value){return value == "50" ? "1" : "0";},} ],
不等于某个值:
'formData.age': [ {type : 'string',pattern:/0/,message: "值要求不能为50",transform(value){return value == "50" ? "1" : "0";},} ],
Range不是规则的属性字段,其通过min和max属性来体现。
如果类型type为string或array,则min和max表示长度。
如果类型type为数值类型(number,integer,float),则min和max表示值的范围。如:
'formData.age': [ { type:'integer', message: "值要求为1-100的整数", min: 1, max:100, trigger:'blur', transform:Number, }, ],
这样,范围校验直接可使用规则的内置属性,在规则中进行描述,也无需用intRangeValidator校验器和正则匹配方式了。
枚举值类型的用法示例:
'formData.idType': [ { type: 'enum', enum: [2,4,6], message: `结果不存在`, trigger: ['change', 'blur'], transform(value) {return Number(value) * 2}, }, ], 或: 'formData.gender': [ { type: 'enum', enum: ['male','female'], message: `结果不存在`, trigger: ['change', 'blur'], }, ],
使用有下列问题:
因此,也可以利用字符串枚举值,来校验范围:
'formData.age': [ { type : 'enum', enum:["1"], message: "值要求为1-100的数", transform(value){ if (!isNaN(value)){ return parseInt(value)>=1 && parseInt(value)<=100 ? "1" : "0"; }else{ return "0"; } } }, ],
注意:此时1e3,9e811被认为是通过校验了,因为parseInt函数只取e前面的数字,而isNaN认为是数字。看来还是需要与正则规则配合才行。
pattern属性,就是正则表达式匹配校验规则,如:
'formData.loginName': [ {required: true, message: "登录名不能为空", trigger: 'blur'}, {pattern:/^[a-zA-Z][\w-. @]*$/, message:'要求为:英文字母开头,后续为字母数字及_-. @符号', trigger: 'blur'} ],
效果与之前的loginNameValidator校验器相同,区别在于loginNameValidator可以复用,保持一个正则校验,如需修改,只需改动一处。而使用pattern则不然。但使用pattern可以少写自定义校验器,给了用户一个选择。
使用pattern属性,可以进行等于某个值某个值的校验。
等于某个值:
{pattern:/120/,message:'必须必须为120',trigger: 'blur'}
关于js正则表达式,可先用js正则表达式在线测试工具测试一下,检查是否达到预期效果。js正则表达式在线测试地址:https://c.runoob.com/front-end/854。
len属性,如果类型为string或array,则冷表示长度。如果为数字型,则表示数字值就是len属性值。
len属性与min、max属性同时出现了,len属性有更高的优先级。
len属性,可用于格式化的字符串校验,如身份证号码长度。
len也可用于等于某个数值的校验,如:
'formData.age': [ { type:'integer', message: "值要求必须为6周岁", len: 6, trigger:'blur', transform:Number, }, ],
空白表示全部由空格组成的字符串,规则的类型必须为string。如果匹配规则,则告警提示。如:
'formData.email': [ {whitespace: true, message: '只存在空格', trigger: 'blur'} ],
值为空格,会提示告警。
如果不希望空格干扰校验,可用transform来处理:
transform(value) { return value.trim();}
message支持i18n,即国际化处理,如集成vue-i18n,message属性的用法如下:
message: () => this.$t( 'about' )
中文语言显示“关于”,英文语言显示“about”。
当然,你也可以换成任意的其它函数,如:
message: () => this.myMessageHandler(MessageId,paramValues)
异步校验器用于远程访问,利用ajax或axios请求数据,对响应数据进行校验或对异常进行提示。
本地页面校验,属于串行校验,逐个检查各字段的校验规则,遇到未通过即返回校验失败。
远程校验,为异步校验,多个请求,响应时间各有不同,响应的先后次序就无法预知。
异步校验的作用:可以将前端和后端针对相同属性字段,使用相同的校验规则,统一由后端提供校验。但这同样增加了前后端沟通和一致性维护的成本。
目前暂时未用到异步校验器,这里用官网的示例:
asyncField1:{asyncValidator: myAsyncValidator} myAsyncValidator可类似validator位置放置。假设放置在data中。 const myAsyncValidator = (rule, value, callback) => { ajax({ url: 'xx', value: value, }).then(function(data) { callback(); }, function(error) { callback(new Error(error)); }); }
Promise异步字段校验:
const myAsyncValidator = (rule, value) => { return ajax({ url: 'xx', value: value, }); }
区别在于Promise异步字段校验,需要使用者自己写上.then/.catch处理逻辑,不支持回调。
异步校验,还涉及到Options属性,
options: { first: true },
first为true,表示多个异步校验遇到第一校验失败就不再处理其它异步校验。
对于对象Object或数组Array的校验,需要具体到每一个元素(成员),这里就要用到Deep rules。
Deep rules涉及到fields和defaultField两个属性。
如官网示例(按照习惯形式略作修改):
对象的深层校验:
rules : { address: [{ type: 'object', required: true, options: { first: true }, fields: { street: [{ type: 'string', required: true }], city: [{ type: 'string', required: true }], zip: [{ type: 'string', required: true, len: 8, message: 'invalid zip' }], }, }], name: [{ type: 'string', required: true }], };
数组的深层校验:
rules : { roles: [{ type: 'array', required: true, len: 3, fields: { 0: [{ type: 'string', required: true }], 1: [{ type: 'string', required: true }], 2: [{ type: 'string', required: true }], }, }], };
数组的深层校验,看起来比较傻,每个成员都要设置校验规则,对于动态数组,似乎也不知该如何设置。
defaultField属性,使我们对字段校验规则有了统一设置的手段。此属性可以作用在校验属性字段上,也可以作用在fields上。
例如:
rules : { urls: [{ type: 'array', required: true, defaultField: { type: 'url' }, }], };
如果是对象数组,该如何设置?可如下方式:
rules : { persons: [{ type: 'array', required: true, defaultField:{ type: 'object', required: true, fields: { address: [{ type: 'object', required: true, fields: { street: [{ type: 'string', required: true }], city: [{ type: 'string', required: true }], zip: [{ type: 'string', required: true, len: 8, message: 'invalid zip' }], }, }], name: [{ type: 'string', required: true }], } } }], };
数组套对象,对象套子对象,看起来有点复杂。
有时候不同模式进入表单,需要应用不同的规则。如新增和编辑操作,显示同一个页面组件。但此时对页面需要校验的属性字段有所不同,如何设置?
有两个处理方案。方案1是配置两套规则集,根据不同模式进行切换;方案2是配置总的规则集,根据不同模式抽取合适的属性字段和规则,动态构建规则集。
切换校验规则集,示例代码如下:
// data 部分 // 当前规则集 rules:{}, // 模式1规则集 rules1:{ ... }, // 模式2规则集 rules2:{ ... }, // methods部分 // 动态切换 // 页面初始化 init(obj,data){ this.prevForm = obj; // 设置页面可见 this.visible = true; // DOM更新之后执行 this.$nextTick(()=>{ // 重置当前页面的所有字段值 this.$refs['form'].resetFields(); if (data){ // 模式1 this.form.patternType = 1; }else{ // 模式2 this.form.patternType = 2; } // 设置校验规则 this.setValidRules(this.form.patternType); } }, setValidRules(patternType){ if(patternType == 1){ this.rules = this.rules1; }else if(patternType == 2){ this.rules = this.rules2; } },
这样,根据不同模式,切换了校验规则集。为了切换规则时,立即执行规则校验,需要设置el-form的validate-on-rule-change为false,即:
<el-form ref="form" :model="form" :rules="rules" :validate-on-rule-change=false class="useredit" label-width="100px" style="line-height: 30px;">
动态构建校验规则集,示例代码如下:
// data 部分 // 当前规则集 rules:{}, // 规则全集 allRules:{ 'formData.loginName': [ {required: true, message: "登录名不能为空", trigger: 'blur'}, {validator:loginNameValidator, trigger: 'blur'} ], 'formData.passwd': [ {required: true, message: "密码不能为空", trigger: 'blur'}, {min: 6, max: 18, message: "密码6-18位", trigger: 'blur'} ], 'formData.email': [ {type: 'email', message: '需要符合email格式', trigger: 'blur'} ], genderLabel: [ {required: true, message: "性别不能为空", trigger: 'change'}, ], userTypeLabel : [ {required: true, message: "用户类型不能为空", trigger: 'change'}, ], deptLabel: [ {required: true, message: "部门不能为空", trigger: 'change'}, ] }, // methods部分 // 动态切换 // 页面初始化 init(obj,data){ this.prevForm = obj; // 设置页面可见 this.visible = true; // DOM更新之后执行 this.$nextTick(()=>{ // 重置当前页面的所有字段值 this.$refs['form'].resetFields(); if (data){ // 模式1 this.form.patternType = 1; }else{ // 模式2 this.form.patternType = 2; } // 设置校验规则 this.setValidRules(this.form.patternType); } }, setValidRules(patternType){ if (patternType == 1){ // 模式1 // 先清空,再设置 this.rules = {}; this.rules['genderLabel'] = this.allRules['genderLabel']; this.rules['userTypeLabel'] = this.allRules['userTypeLabel']; this.rules['deptLabel'] = this.allRules['deptLabel']; this.rules['formData.email'] = this.allRules['formData.email']; } else{ // 模式2,需要验证登录名和密码 this.rules = {}; this.rules['formData.loginName'] = this.allRules['formData.loginName']; this.rules['formData.passwd'] = this.allRules['formData.passwd']; this.rules['genderLabel'] = this.allRules['genderLabel']; this.rules['userTypeLabel'] = this.allRules['userTypeLabel']; this.rules['deptLabel'] = this.allRules['deptLabel']; this.rules['formData.email'] = this.allRules['formData.email']; } },
同样也需要设置el-form的validate-on-rule-change为false。
有的表单,使用了可编辑的动态表格,如添加一数据行,直接在数据行中输入数据,然后提交。此时需要对数据行各字段的输入进行校验。
有2个方案。
方案1使用Deep rules的defaultField,对对象数组进行字段校验,见上面的示例代码。
方案2,在el-form-item层级使用rules属性绑定该字段规则。
多字段联合校验应用场合还是比较常见的,如文本开始的问题,不同ID类型,有不同的校验规则;如密码验证,两次密码要相同;如购买数量不能超过库存数量,时间段开始时间要不大于结束时间,等等。
关键技巧,利用校验器的第一个参数rule,添加一个或若干个自定义属性,传递信息到校验器进行处理。使用方法如下:
作为示例,假设'formData.email'字段校验依赖于userType的值。
'formData.email': [ {validator : idFieldWithTypeValidator, trigger: 'blur',} ],
没有办法初始绑定:
'formData.email': [ {validator : idFieldWithTypeValidator, trigger: 'blur','userType':this.form.formData.userype} ],
这样写,浏览器调试器显示错误,提示调用resetFields出错。
因此,正确的形式为:
'formData.email': [ {validator : idFieldWithTypeValidator, trigger: 'blur',} ],
或:
'formData.email': [ {validator : idFieldWithTypeValidator, trigger: 'blur','userType':0} ],
然后,在页面初始化时,或选择框选择改变的chage事件方法中,动态设置规则中userType属性的值:
this.rules['formData.email'][0]['userType'] = this.form.formData.userType;
试验结果,用$set没法动态绑定,即下列语句没有作用:
this.$set(this.allRules['formData.email'][0],'userType',this.form.formData.userType);
好了,现在可以编写一个联合校验器idFieldWithTypeValidator了。简单起见,在data部分编写:
const idFieldWithTypeValidator = (rule, value, callback) =>{ // 获取用户类型 console.log(rule); return callback(); }
测试一下,在浏览器控制台输出rule的打印信息如下:
{ "userType": 2, "field": "formData.email", "fullField": "formData.email", "type": "string" }
此时,userType已经通过rule参数传入,现在可以进行联合校验了。
import {loginNameValidator,phoneNoValidator,idNoValidator,eMailValidator} from '@/common/validator.js' export default { data() { // 不同类型情况下的ID字段校验器 const idFieldWithTypeValidator = (rule, value, callback) =>{ // 获取用户类型 console.log(rule); if (rule.userType == 1){ // 手机号码 phoneNoValidator(rule, value, callback); }else if(rule.userType == 2){ // 身份证号码 idNoValidator(rule, value, callback); }else if(rule.userType == 3){ // email eMailValidator(rule, value, callback); } } return { .... } }, ... }
其中phoneNoValidator、idNoValidator、eMailValidator分别是手机号码校验器、身份证号码校验器、邮箱格式校验器,由validator.js中输出,idFieldWithTypeValidator校验器根据userType参数的取值不同,分别调用了相关的validator类型的校验器。当然,在idFieldWithTypeValidator的方法代码中,也可以将各个校验器的代码搬过来,不调用外部校验器。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
javascript将时间转毫秒的方法:1、通过“(new Date(startDate)).getTime();”将日期转换为毫秒;2、通过“Date.parse(new Date(arr[0]...)”方法将日期转化为毫秒。
vue-router安装步骤是什么,使用是怎样?一些朋友可能会遇到这方面的问题,对此在下文小编向大家来讲解一下,内容详细,易于理解,希望大家阅读完这篇能有收获哦,有需要的朋友就往下看吧!
文我们来了解React diffing算法的内容,下文会给大家来详细的介绍diffing算法的原理,对大家学习和理解diffing算法很有帮助,有这方面学习需要的朋友不妨了解看看,那么接下来就跟随小编来学习一下diffing算法吧。
这篇文章主要给大家介绍echarts饼图分区之间的空隙效果实现,这个效果能明显的各个板块的占比,实现效果及代码如下,感兴趣的朋友接下来跟随小编一起了解看看吧。
本篇文章给大家带来了关于javascript的相关知识,在 JavaScript 中,不像 Java 等语言,它没有任何打印或者输出方法的,在js中通过使用4种方式来输出数据,本文通过实例代码给大家详细介绍,希望对大家有帮助。
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008