Loading

项目踩坑

一、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的生命周期:

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配置:

echats

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方式的请求。
posted @ 2020-08-26 23:57  dBevil  阅读(352)  评论(0编辑  收藏  举报