项目踩坑
一、vue
1、v-model实现数据的双向绑定,需要在data中声明初始值,因为v-model 会忽略所有表单元素的 value、 checked、selected attribute 的初始值,将 Vue 实例的数据作为数据来源。可用提供一个值为空的禁用 选项用于解决ios用户无法选择第一个选项的问题。
<option disabled value="">请选择</option>
2、:disabled=Boolean实现禁用。
<option value="" disabled>请选择</option>
3、一个Option就是一个下拉选项,可通过v-for循环定义好的数组、对象或整数实现列表渲染,需要通过:value接收Option选中的值
<Select class="area" v-model="tstadium.area">
<Option v-for="item in stateList" :value="item.value" :key="item.value" name="area">
{{item.label }}
</Option>
</Select>
4、
v-for="item in items"
分别代表数组元素迭代的别名和源数组;其中in可用of代替。
v-for="(item,index) in items"
index为数组索引。
当v-for循环的是一个对象时,可表示为v-for="(value,key) in object
表示对象的键和值。
使用v-for时尽量加上:key,这是为vue循环出来的每一项都提供唯一的标识;v-bind:key="item.id"这种 表示形式。
5、当v-for和v-if处于同一节点时,v-for 的优先级比 v-if 更高。如果是想有条件的跳过循环执行,可将for包 在if里面。
6、条件渲染:
v-if v-else-if v-else
搭配,其中v-else需要紧跟在v-if或v-else-if后面才能够被识别。
如果在v-if指令后面添加了key,条件切换时页面都将会重新被渲染,否则共用。
7、v-show可实现的功能和v-if相同,只是v-show是切换css的display属性,而v-if需要重新渲染dom,
所以如果需要频繁切换最好使用v-show以减少开销,否则使用v-if为好。
8、class的绑定:
<div class="static" v-bind:class="{ active: isActive, 'text-danger': hasError }"></div> data: { isActive: true, hasError: false } 最终结果为:<div class="static active"></div> 可以使用三元运算符动态改变class如: <div :class="isActive ? activeClass : ''"></div> 如果条件为true时才会加载类。
9、style的绑定:
<div v-bind:style="styleObject"></div> data: { styleObject: { color: 'red', fontSize: '13px' } }
表示将对象中的属性与值赋值给style,看似是css,其实是js对象,需要使用驼峰命名或短横线分隔 (用引号括起来) 来命名
10、数据与方法:
使用 Object.freeze(obj),会阻止修改现有的 property,因此页面不会进行渲染更新。
vue实例属性和方法前面如果有$表示为vue自带的property 与方法,与用户自定义的区别。
11、实例创建之后,可以通过 vm.$data 访问原始数据对象。
Vue 实例也代理了 data 对象上所有的 property,因此访问 vm.a 等价于访问 vm.$data.a。
12、使用v-once,执行一次性插值,当数据改变时,插值处的内容不会更新,但会影响到该节点上的其它数 据绑定。
13、使用v-html,输出真正的 HTML,不可以在大括号中直接放入绑定的数据(HTML代码)。
14、vue的生命周期:
<script> var vm = new Vue({ el: "#app", data: { msg: "ok" }, methods: { show() { console.log("执行了show方法") } }, /** * 实例创建期间的四个函数 */ // data和methods中的数据还没有被初始化 beforeCreate() { //这是第一个生命周期函数,表示实例完全被创建之前会执行它 // console.log(this.msg) //提示未定义 // 注意:在beforeCreate生命周期函数执行的时候,data和methods中的数据都还没有被初始化 }, // data和methods中的数据被初始化 created() { // 这是遇到的第二个生命周期函数 // console.log(this.msg); //可以被调用 // this.show(); // 在created中,data和methods中的数据都已经被初始化;如果要调用methods中的方法或者data中的数据,最早要在created中调用 }, // 判断是否设置了el挂载点;vue开始编译模板,在内存中生成最终的模板字符串,然后将他渲染为内存中的DOM,还没有将此模板渲染到真正的页面中去 beforeMount() { //第三个生命周期函数,表示模板已经在内存中编译完成,还没渲染到页面中 // console.log(document.getElementById("h3").innerText); //输出模板字符串 //在此周期执行时,页面中的元素还没有真正替换,还只是之前写的模板字符串 }, // 将内存中编译好的模板替换到页面中去 mounted() { //表示内存中的模板已经渲染到页面中, 用户可以看到页面;整个实例已经初始化完成,进入运行阶段 // console.log(document.getElementById("h3").innerText); //输出页面上真实的数据 // 此时可以获取到页面中的值,这是实例创建期间的最后一个钩子函数,此时如果没有其他操作的话,它将在内存中一动不动 // 如果需要操作DOM中的节点,最早需要在此周期中操作 }, /** * 组件运行阶段的生命周期函数,只有data中的数据发生改变时才会进入环节,最少执行0次 */ // 当执行此函数时,页面上的数据时旧的,但是data中的数据是最新的,页面尚未和最新的数据保持同步 beforeUpdate() { //界面还没有被更新,但是数据被更新了 // console.log('页面上的数据:' + document.getElementById("h3").innerText) // console.log('data中的数据:' + this.msg) // 当data中的数据发生改变时才会触发此函数 }, // 先根据内存中最新的数据重新渲染出一份最新的dom树,当内存中最新的DOM树被更新完成之后,就会重新渲染到页面中去,从而完成model到view的更新 updated() { // 此函数中的数据和页面上内容都是最新的 }, /** * 组件销毁时执行的生命周期函数 */ beforeDestroy() { // 当执行此函数时实例就已经从运行阶段进入到了销毁阶段,实例身上所有的data methods 过滤器及指令等都还处于可用状态,还没有真正执行销毁的过程 }, destroyed() { // 当执行到此函数时,组件已经被完全销毁,里面所有的东西都不可用 } }); </script>
(一)、beforeCreate
第一个生命周期函数,表示实例完全被创建出来(vue初始化)之前,会执行它
注意: 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 属性与方法定义都还没有没初 始化,所以无法获取到data中的数据和方法(二)、created
在 created 中,data 和 methods 都已经被初始化好了!
如果要调用 methods 中的方法,或者操作 data 中的数据,最早(最好),在 created 中操作(三)、beforeMount
第三个生命周期函数,表示 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中。
在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串(四)、mounted---------推荐在此生命周期中获取数据:Ajax、axios(需要ES6支持)
第四个生命周期函数,表示,内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
注意: mounted 是 实例创建期间的最后一个生命周期函数,当执行完mounted
就表示,实例已经被完全创建好了,
此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动,表示vue实例已经初始化完毕了,组建已脱离创建阶段,进入运行阶段了。(五)、beforeUpdate()
这时候,表示 我们的界面还没有被更新,但是vue中的数据已经更新了(六)、updated
updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的(七)、beforeDestroy
毁之前执行,当beforeDestroy函数执行时,表示vue实例已从运行阶段进入销毁阶段,
vue实例身上所有的方法与数据都处于可用状态(八)、destroyed
当destroy函数执行时,组件中所有的方法与数据已经被完全销毁,不可用(九)、activated
页面出现的时候执行 activated生命周期函数,跟 监听 watch 有类似的作用。
activated生命周期函数,是配合 keep-alive 进行使用。进入页面时,mounted 与 activated 生命周期函数都会执行,
当前 keep-alive 时,进行了缓存,这时返回上一页 ,mounted生命周期函数不会执行,而 activated 会执行。
注意:新增(十)、deactivated
页面消失的时候执行,deactivated生命周期函数。是配合 keep-alive 进行使用
注意:新增
15、在vue中实现对页面dom的操作:
vm.$nextTick(function () {在此操作dom});
16、页面渲染之前会闪烁一下的问题:在挂在的标签内写个属性:v-clock,再在style中使用属性选择器设为
[v-clock]{ display:none; }
17、计算属性:内存中运行,可以理解为缓存,将不经常变化的结果在内存中缓存以节约浏览器的开销。
html中调用vue中methods的方法需要加上括号,computed中的方法不需要加括号(因为是个属性);methods和computed中的方法尽量不重名,重名后methods中的优先级高。
18、watch:用于动态监听input中的值:可在此实现实时搜索功能
watch: { //动态监听输入框中的值 'name': { //name为data中定义的变量 handler: function (newValue, oldValue) { //newValue为新输入的值,oldValue为之前的值 if (newValue == "" || newValue == null) { //实现逻辑 }else{ //实现逻辑 } }, // 深度监听 监听对象,数组的变化 deep: true } }
19、Vue.config.keyCodes.f2 = 113;自定义键盘事件,将f2指定为113键盘码,在页面直接使用(keyup.f2)
20、使用Vue.directive('focus',{函数}),定义全局指令(不加s),参数1为指令的名称,定义时不用加v-,在调用时需要加上;参数2为一个对象,对象上有一些指令相关的函数,在相关阶段执行相关的操作。
自定义私有指令:
21、在axios请求数据时,get请求方式使用params传参数;post请求方式使用data传递参数。
22、axios传json到后台:
// 在axios中加入下面代码 data: JSON.stringify(vm.studentInfo), headers:{ "Content-Type": "application/json; charset=UTF-8" }
// 后台接口使用String接收并转为Java对象 public R register(@RequestBody String registerObj){ JSONObject jsonObject = JSONObject.fromObject(registerObj); //将json字符串转Java对象 RegisterForm form = (RegisterForm) JSONObject.toBean(jsonObject,RegisterForm.class); System.out.println("java对象:" + form); }
二、JavaScript
1、jQuery为页面中的标签添加属性:$(选择器).attr("属性名", "属性值");
2、split();分割数组。push();追加到数组最后并返回一个新的数组。math.abs();返回一个数的绝对值。
4、获取指定日期前后的天数:需要通过毫秒计算
/** * 获取当前指定前后天数对应的年月日 * @param AddDayCount 指定日期前后的天数 * @returns {string} 202004420 * @constructor */ function GetSagginDateStr(AddDayCount) { var nDate = new Date().getTime(); //获取当前时间的毫秒值 var millSeconds = Math.abs(nDate) + (AddDayCount * 24 * 60 * 60 * 1000); //将两个毫秒值相加 var rDate = new Date(millSeconds); //将毫秒值转为一个标准时间 var year = rDate.getFullYear(); var month = rDate.getMonth() + 1; if (month < 10) { month = "0" + month; } var date = rDate.getDate(); if (date < 10) { date = "0" + date; } return year + "" + month + "" + date; }
5、获取时间的毫秒值:
new Date().getTime();
6、获取时间戳:Date.now();
7、Es6相关语法:
const用于声明一个只读 常量,且必须在声明常量时就需要对其进行赋值,一旦声明就不可再改变(内存地址不变); let用于声明一个变量,与var类似,但是只在它声明的代码块内有效。 二者都需要先声明再使用。 在ES5中,变量声明只有 var 和function两种方法, 在ES6中,添加了 let 和 const,还有 class 和 import 两种命令
8、数组的解构和赋值:通过匹配位置赋值
let [a,b,c] = [1,2,3]; //分别打印abc,会分别得到123 //如果左右的值匹配不成功就会返回undefined //右边的值需要是能够遍历的解构或者数组,否则会报错
9、对象的解构和赋值:通过对象属性名进行赋值
let {name,age} = {name:'张三',age:18} //如果名字匹配不上就将报undefined let {log} = console; //可以将对象中的方法赋值给某个变量 log("hello world"); //将会输出“hello world” /** *对象结构赋值的内部机制,即先找到同名的属性,再将属性复制给同名的变量,真正被赋值的后者,而不是前者 *如下代码中,foo只是匹配模式,name才是真正的变量 */ let {foo:name} = {foo:'hello'}; console.log(name); let {name,age=18} = {name:'张三',age:undefined} //如果值为undefined时,会执行默认值
10、字符串的解构:
let [a,b,c,d,e] = "hello"; //会将字符串拆分为单个字母 let {length:len} = "hello"; //返回字符串的长度
用途:
/** 001、交换变量的值 */ let x = 10; let y = 20; [x,y] = [y,x]; /** 002、获取函数的多个返回值 */ //获取返回数组的多个值 function example(){ return [1,2,3] } let [a,b,c] = example(); //获取返回对象的多个值 function example2(){ return{ name:'hello', slogan:'world' } } let {name,slogan} = example2(); /** 003、提取json数据 */ let jsonData = { name:'test', age:18, like:'frisbee' }; let [name,age,like] = jsonData; /** 004、设置函数参数的默认值 */ function sendMsg(url,{ async=true, beforeSend = function(){}, global=true } = {}){ //..函数处理逻辑 } /** 005、输入模块的指定方法 */ const {sourceMapConsumer,SourceNode} = require("source-map") /** 06、遍历Map */ const map = new Map(); map.set('first','hello'); map.set('second','world'); for(let [key,value] of map){ console.log(key + ":" + value); }
11、str.padStart(maxLength,'String'),当字符串的位数不足指定的maxLength时就在开始填充指定的string;同时还有padEnd方法在尾部填充。
12、focus()方法可以获取到焦点
13、去掉字符串前面的0:
console.log(s.replace(/\b(0+)/gi,""));
14、ECharts配置:
15、立即执行函数:
(function(){ // js代码,里面定义的都是局部的,从而避免命名污染 })(); (function(j){ // j为内部调用 // js代码 }(i)); // i为外部参数传递的入口 !function(){ }(); void function(){ }();
16、cookies、sessionStorage、localStorage的区别:
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递,大小不可超过4k。 sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存,可达5M或更大。 localStorage只有手动才能删除,除非一直生效。 sessionStorage当前浏览器关闭后自动删除。 cookie在过期时间内有效,即使页面或浏览器关闭。
17、当前标签打开新页面:
window.location.href = "../html/login.html";
18、iframe标签子页面操作父页面:
$(window.parent.document).find('footer').css("display", "none");
三、html
1、使背景不能左右滑动:
body{ overflow-x: hidden; }
2、微信使用input-file出现没有应用可执行此操作:是因为 input-file添加了accept属性 ,删除并在js判断格式
<input type="file" @change="getFile"> getFile(){ let previewImgs = e.target.files[0] if (!new RegExp("(jpg|jpeg|gif|png)+","gi").test(previewImgs.type)) { Toast('您上传的图片格式有误,请重新上传~') return } }
3、使整个网页变灰:来源
html { filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1); -webkit-filter: grayscale(100%); }
4、网页无法选择:来源
/*在HTML的body标签中加入相关代码*/ οnpaste="return false" /*不准粘贴*/ οncοpy="return false;" /*不准复制*/ oncut="return false;" /*防止剪切*/ onselectstart = "return false" /*不准选择*/
5、在图片上点击查看大图(将图片从新页面打开):
<img title='点击查看大图' onclick='window.open("src")' src=src width=100% height=100%>
四、Linux
1、jar文件在后台不间断运行:
nohup java -jar xxx.jar >temp.txt & nohup 意思是不挂断运行命令,当账户退出或终端关闭时,程序仍然运行 & 代表在后台运行 >temp.txt 表示将运行日志保存到temp文件中
五、Java
1、spring boot获取yml中的配置信息:在配置文件中编写数据、导入依赖、创建实体类、使用
# 配置信息 we-chat-info: token: badmin appid: wx73deaf87124512b7e secret: 87fe6292ca050b1ca541b148e2512345
<!--导入配置文件处理器,获取application.yml中的数据,第二个测试可不需要--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
/** * 创建实体类 */ @Data @Configuration @ConfigurationProperties(prefix = "we-chat-info") //yml中的根节点名 public class SysWeChat implements Serializable { private static final long serialVersionUID = 1L; /** *节点中对应的各个属性名 */ private String token; private String appid; private String secret; }
/** * 调用 */ @Autowired private static SysWeChat sysWeChat; private static final String TOKEN = sysWeChat.getToken(); private static final String APPID = sysWeChat.getAppid(); private static final String SECRET = sysWeChat.getSecret();
/** * 测试 */ @RunWith(SpringRunner.class) @SpringBootTest public class WeChatTest { @Autowired private WeChatConfig weChatConfig; @Value("${we-chat-info.token}") private String token; @Test public void testInfo() { System.out.println(weChatConfig.getAppid()); System.out.println(token); } }
2、Java对象转json字符串:
//1、使用JSONObject JSONObject json = JSONObject.fromObject(stu).toString(); //2、使用JSONArray JSONArray array=JSONArray.fromObject(stu).toString();
3、json字符串转java对象:
//1、使用JSONObject JSONObject jsonObject=JSONObject.fromObject(objectStr); Student stu=(Student)JSONObject.toBean(jsonObject, Student.class); //2、使用JSONArray JSONArray jsonArray=JSONArray.fromObject(arrayStr); //获得jsonArray的第一个元素 Object o=jsonArray.get(0); JSONObject jsonObject2=JSONObject.fromObject(o); Student stu2=(Student)JSONObject.toBean(jsonObject2, Student.class);
4、list转json字符串:
List<Student> lists=new ArrayList<Student>(); lists.add(stu); //1、使用JSONObject //JSONObject listObject=JSONObject.fromObject(lists); //2、使用JSONArray JSONArray listArray=JSONArray.fromObject(lists);
5、json字符串转list:
List<Student> list2=(List<Student>)JSONArray.toList(JSONArray.fromObject(arrayStr), Student.class); for (Student stu : list2) { System.out.println(stu); } //转化为数组 Student[] ss =(Student[])JSONArray.toArray(JSONArray.fromObject(arrayStr),Student.class); for (Student student : ss) { System.out.println(student); }
6、map转json字符串:
Map<String,Student> map=new HashMap<String,Student>(); map.put("first", stu); //1、JSONObject JSONObject mapObject=JSONObject.fromObject(map); System.out.println("mapObject"+mapObject.toString()); //2、JSONArray JSONArray mapArray=JSONArray.fromObject(map); System.out.println("mapArray:"+mapArray.toString());
7、json字符串转map:
//JSONObject JSONObject jsonObject=JSONObject.fromObject(strObject); Map map=new HashMap(); map.put("first", Student.class); //使用了toBean方法,需要三个参数 MyBean my=(MyBean)JSONObject.toBean(jsonObject, MyBean.class, map); System.out.println(my.getFirst()); /** * 使用toBean()方法是传入了三个参数,第一个是JSONObject对象,第二个是MyBean.class,第三个是一个Map对象。 * 通过MyBean可以知道此类中要有一个first的属性,且其类型为Student,要和map中的键和值类型对应,即,first对应键 first类型对应值的类型。 */
8、上传文件:使用post方式提交
@RequestMapping("/file") public String file(@RequestParam("file") MultipartFile file, String creditCode) { if (file.isEmpty()) { return "请选择文件"; } Long date = System.currentTimeMillis(); String fileRealName = file.getOriginalFilename(); // 获取文件原始名称 String extension = getExtension(fileRealName); // 获取文件扩展名 String fileName = date + "." + extension; // 拼接文件名 // 路径如:D:\internship\image\afterInternship String filePath = fileUtil.getRootPath("image" + File.separator + "afterInternship"); // 如果不存在文件夹就创建一个 if (!new File(filePath).isDirectory()) { new File(filePath).mkdir(); } File dest = new File(filePath + fileName); try { file.transferTo(dest); return fileName; } catch (IOException e) { } return "上传失败!"; }
9、对象转map
Map<String, Object> tempMap = new HashMap<>(); // 将对象转为map BeanInfo beanInfo = Introspector.getBeanInfo(对象.getClass()); PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor property : propertyDescriptors) { String key = property.getName(); if (key.compareToIgnoreCase("class") == 0) { continue; } Method getter = property.getReadMethod(); Object value = getter != null ? getter.invoke(对象) : null; tempMap.put(key, value); }
10、controller注解:
public R xxx(@RequestBody Object object) //用于接收前端post请求发送的data数据,后端使用对象接收。 public R xxx(@RequestParam Map<String, Object> params) //用于接收前端get方式发送的params数据;params.get("userId").toString(); public R xxx(@RequestBody String objData) //用于接收前端post发送的json字符串,后端使用JSONObject.fromObject(objData)将其转为json对象;如果对象中有多余的值,可通过json对象的remove方法将其删除;再通过JSONObject.toBean(jsonObject,Object.class)将其转为指定对象。 @PostMapping("login/{userId}") //前端在发送请求时直接将参数拼接在url后面,使用斜杠隔开;后端在方法上使用@PathVariable("userId") String uId接收。 @RequestMapping(value = "/wx", method = {RequestMethod.GET, RequestMethod.POST}) //可同时接收post和get方式的请求。