2、vueJS框架-day02
vueJS框架-day02
1.组件化系统
组件:就是一个特定的前端功能模块,可以创建多个一样的组件来形成页面。
语法:
var App = Vue.extend(option); var App = Vue.extend({ name:"App", //数据 data:function{ return{} }, //模板 template:`` }); //第二中写法 var App = { name:"App", //数据 data:function{ return{} }, //模板 template:`` }
需要注册才能在挂载的目标元素上使用。
通过vue选项中的components
<div id="app"></div> <script> var App = { name:"App", //数据 data:function{ return{} }, //模板 template:`` } //Vue对象 new Vue({ el:"#app", data:function(){ return{} }, //注册组件 components:{ "app":App }, template:` //使用组件 <app /> ` });
一般来说我们只需要组装组件的,所以在App的一个大组件上组件其他的小组件,这样就不需要在Vue对象上组装了。(注意:组件的data的类型一定是一个函数,还必须带返回值)
<div id="app"></div> <script> //一个小组件 var Phone = { data:fucntion(){ return{} }, template:` <li> <span>123</span> </li> ` } //一个大组件里面组装一个小组件 var App = { name:"App", //数据 data:function{ return{} }, //注册小组件 components:{ "phone-li":Phone } //模板 template:` <div> <ul> //使用小组件 <phone-li/> </ul> </div> ` } //Vue对象 new Vue({ el:"#app", data:function(){ return{} }, //注册组件 components:{ "app":App }, template:` //使用组件 <app /> ` });
1.2组件的传值
通过props[“属性1”:"值1",“属性2”:"值2",]暴露自己的外在属性,从而传值进来。
props[属性1:值1,属性2:值2]
var Phone = { name:"Phone", template:` <li class="phone"> <img :src="phone.imgurl" alt=""> <div>{{phone.name}}</div> <span>{{phone.desc}}</span> <p>{{phone.price}}</p> </li> `, data:function(){ return{ } }, //通过暴露自己的外在属性 props:["phone"] } var App = Vue.extend({ template:` <ul id="phone"> //同过单向绑定进行数据的流动 <phoneLi v-for=" ph in phones" :phone="ph"/> </ul> `, data:function(){ return{ phones:[ {name:"Redmi K30",desc:"120Hz流速屏,全速热爱",price:"1599元起",imgurl:"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/2c16238f786e4f93bdb175d7bf21aa47.jpg?thumb=1&w=250&h=250&f=webp&q=90"}, {name:"Redmi K30 5G",desc:"120Hz流速屏,全速热爱",price:"2599元起",imgurl:"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/53641901fbc28cbcdb495b17fdf69e46.jpg?thumb=1&w=250&h=250&f=webp&q=90"}, {name:"Redmi K30 6G",desc:"120Hz流速屏,全速热爱",price:"3599元起",imgurl:"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/07270cc09689eb9b13b29aa9f6bc41eb.jpg?thumb=1&w=250&h=250&f=webp&q=90"}, ] } }, components:{ phoneLi:Phone } });
1.3全局组件
当我们需要在别的地方也需要该组件时,不仅仅作用于当前组件,我们就需要定义全局的组件,我们之前定义的方式是局部的组件,仅作用于声明注册的那个组件。
//声明组件 var Temp = { name:"Temp", data:function(){ return{} }, template:`` } //全局注册 Vue.component("temp",Temp);
1.4组件的生命周期
beforeCreate:创建Vue之前,用来初始化事件等
Created:创建之后
beforeMount:创建DOM对象之前
mounted:创建DOM对象之后,可用来网络请求,初始化数据
(beforeUpdate:在数据更新的时候
updated:数据更新完成后
)可能会涉及多次调用
beforeDestroy:销毁vue之前
destroyed:销毁vue之后
后面是跟着一个函数的,用在vue的选项中,当然组件也是适用的。
<div id="app"></div> <script> new Vue({ el:"#app", data:function(){ return {} }, template:``, mounted:function(){ //当dom创建完成后就会执行 console.log("mounted"); } });
使用组件仿小米:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <style> body{ background: #f5f5f5; margin: 0%; padding: 0%; } .phone{ width: 234px; height: 300px; text-align: center; background: white; } ul,li{ list-style: none; } .phone img{ width: 160px; height: 160px; margin: 20px 0 ; } .phone div{ font-size: 14px; } .phone span{ font-size: 12px; color: turquoise; } .phone p{ font-size: 13px; color: red; } #phone li{ float: left; margin-left: 20px; } </style> <script src="./js/vue-2.6.10.js"></script> </head> <body> <div id="app"></div> <script> var Phone = { name:"Phone", template:` <li class="phone"> <img :src="phone.imgurl" alt=""> <div>{{phone.name}}</div> <span>{{phone.desc}}</span> <p>{{phone.price}}</p> </li> `, data:function(){ return{ } }, props:["phone"] } var App = Vue.extend({ template:` <ul id="phone"> <phoneLi v-for=" ph in phones" :phone="ph"/> </ul> `, data:function(){ return{ phones:[ {name:"Redmi K30",desc:"120Hz流速屏,全速热爱",price:"1599元起",imgurl:"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/2c16238f786e4f93bdb175d7bf21aa47.jpg?thumb=1&w=250&h=250&f=webp&q=90"}, {name:"Redmi K30 5G",desc:"120Hz流速屏,全速热爱",price:"2599元起",imgurl:"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/53641901fbc28cbcdb495b17fdf69e46.jpg?thumb=1&w=250&h=250&f=webp&q=90"}, {name:"Redmi K30 6G",desc:"120Hz流速屏,全速热爱",price:"3599元起",imgurl:"https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/07270cc09689eb9b13b29aa9f6bc41eb.jpg?thumb=1&w=250&h=250&f=webp&q=90"}, ] } }, components:{ phoneLi:Phone } }); new Vue({ el:"#app", data:function(){ return{ } }, components:{ app:App }, template:` <app /> ` }); </script> </body> </html>
2.axios(ajax请求)
vue的ajax请求;基于HTTP的请求。
查阅api的网址:https://www.npmjs.com/
下载jar的地址:https://mvnrepository.com/
对Ajax的封装有两个请求,一个get,一个是post.
axios 是一个http client,可以在浏览器端直接发送http请求。
then:function(response){
}
response:包含很多信息,比如data,status等
2.1get
语法:
axios.post('/user', { firstName: 'Fred', lastName: 'Flintstone' }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
<div id="app"></div> <script type="text/javascript"> new Vue({ el:"#app", template:` <div> <span v-if="users.length>0" v-for="user in users "> {{user}} </span> <button @click="send">send</button> </form> </div> `, data:function(){ return { users:[] } }, methods:{ send:function(){ var self = this; axios.get('get').then(function(resp) { console.log(resp.data); self.users = resp.data; }); } } }); </script>
2.2post
语法分为两种;
-
不是表单请求的方式,是一个json字符串的方式来提交数据的
-
不可以用getParameter();来接收数据
-
语法:
-
ar user = { "username" :"大黄", "pwd": "123" }; axios.post('post',user).then(function(resp) { console.log(resp.data); }); <div id="app"></div> <script type="text/javascript"> new Vue({ el:"#app", template:` <div> <button @click="send">send</button> </form> </div> `, data:function(){ return { username:"", password:"" } }, methods:{ send:function(){ var user = { "username" :"大黄", "pwd": "123" }; axios.post('post',user).then(function(resp) { console.log(resp.data); }); } } }); </script> servlet接收数据:
//现在请求的类型不是form表单,所以不能使用getParameter()来接收参数 //需要通过流的方式 BufferedReader br = req.getReader(); String str = null; StringBuilder sb = new StringBuilder(); while((str = br.readLine()) != null) { sb.append(str); } //转为json的对象 Gson gson = new Gson(); //声明一个User.class对象来接收 User user = gson.fromJson(sb.toString(), User.class); System.out.println(user);
-
-
表单类型的数据:
-
语法
const params = new URLSearchParams(); params.append('param1', 'value1'); params.append('param2', 'value2'); axios.post('url', params); <div id="app"></div> <script type="text/javascript"> new Vue({ el:"#app", template:` <div> <form action=""> <input type="text" v-model="username"><br/> <input type="password" v-model="password"><br/> <input type="submit" v-on:click="submit"> </form> </div> `, data:function(){ return { username:"", password:"" } }, methods:{ submit:function(){ const params = new URLSearchParams(); params.append('username', this.username); params.append('password', this.password); axios.post('login', params); } } }); </script> servlet接收参数:
String username = req.getParameter("username"); String password = req.getParameter("password"); System.out.println(username+","+password);
-
3.过滤器
vue的过滤器,可以对数据进行拦截-》改造处理-》新数据 作用范围可以是组件内过滤器,也可以是全局过滤器。
3.1过滤器的基础
<div id="app"> //使用过滤器,conver过滤器名字 <span>{{ msg | conver }}<span> </div> <script> var App = { name:"App", data:function(){ reuturn{ msg:'' } }, //局部声明过滤器 filters:{ //过滤器名字,不传参数的时候,默认有一个参数 conver:function(data){ //可以对数据进行改造了 return "RMB"+data; } } } new Vue({ el:"#app", data:..., components:{ app:App } template:`<app />` });
3.2过滤器传递多个参数
<div id="app"> //使用过滤器,conver过滤器名字,传递了test,test2参数 <span>{{ msg | conver("test","test2") }}<span> </div> <script> var App = { name:"App", data:function(){ reuturn{ msg:'' } }, //局部声明过滤器 filters:{ //过滤器名字,参数的时候,第一个默认是原始数据,其他都是通过过滤器传递过滤的参数 conver:function(data,arg0,arg1){ //可以对数据进行改造了 return "RMB"+data+arg0+arg1; } } } new Vue({ el:"#app", data:..., components:{ app:App } template:`<app />` });
3.3过滤器的嵌套
过滤器中还可以嵌套其他的过滤器。
先从原始数据开始,第一个过滤完成后的结果作为下一个过滤器的原始数据传进去。所以之前的过滤器要有返回值,不然会报错。
<div id="app"> //使用过滤器,conver过滤器1,conver2过滤器2 <span>{{ msg | conver | conver2 }}<span> </div> <script> var App = { name:"App", data:function(){ reuturn{ msg:'' } }, //局部声明过滤器 filters:{ //过滤器名字,参数的时候,第一个默认是原始数据,其他都是通过过滤器传递过滤的参数 conver:function(data){ //可以对数据进行改造了 return "RMB"; }, conver2:function(data){ return data+"$"; } } } new Vue({ el:"#app", data:..., components:{ app:App } template:`<app />` });
4.计算属性
有些属性我们在数据库中没有直接定义的,可以在通过计算的到,不需要在data中声明,需要在computed中声明。语法为: 变量名:function(){ 属性1和属性2等返回结果就是计算得到的属性}。
当属性中的其中一个发生变化后,计算属性也会随之变化。
<div id="app"> //count是计算的属性 <span>{{ count }}<span> </div> <script> var App = { name:"App", data:function(){ reuturn{ sal:100, com:200 } }, //计算属性 computed:{ count:function(){ //需要转换属性的类型 return (this.sal-0)+(this.com-0); } } } new Vue({ el:"#app", data:..., components:{ app:App } template:`<app />` });
5.监听器
当属性发生变化时,我们可以监听属性的变化情况。
当属性的类型是简单的数据类型时,可以用普通的监听器。不能监听到有地址的数据。
<div id="app"> //count是计算的属性 <input type="text" v-model:value="msg" /> </div> <script> var App = { name:"App", data:function(){ reuturn{ msg:"" } }, //监听器 watch:{ //msg是被监听的属性 msg:function(newVal,oldVal){ //这里可以使用两个参数,一个是变化前的值newVal,,一个是变化后的值,oldVal } } } new Vue({ el:"#app", data:..., components:{ app:App } template:`<app />` });
然而,对于复杂的数据类型普通的监听器是不起作用的,比如数据,对象等复杂的数据类型,需要用深度的监听器。
对应新值和旧值是无法监听的。
watch: { msg:function(newVal,oldVal){ console.log(newVal,oldVal); }, //监听到对象的深度监听 stu: { deep: true, handler: function (newVal, oldVal) { console.log("监听到了stu的属性发生变化"); } }, },
6.在vue中获取原生js对象
在组件中使用$refs.(ref=”“)来获取到js对象。
比如在:
<input type="text" ref="id" /> vue中 $refs.id就可以获取到了。
7.单选框取值和默认状态的问题
value还是原来的value,v-model不绑定value而是绑定后台传过来的值。
//HTML <input type="radio" name="radios" value="1" v-model="param"><label>one</label> <br> <input type="radio" name="radios" value="2" v-model="param"><label>two</label> <br> <input type="radio" name="radios" value="3" v-model="param"><label>three</label> /JS export default{ data(){ return{ param:'1' //设置默认值为1,即设置第一个单选框为选中状态 } } }
8.上传文件
前端页面
<div class="row" id="app"> <div class="col-sm-10 col-sm-offset-1"> <input type="file" class="upload" @change="addImg" ref="inputer" multiple accept="image/png,image/jpeg,image/gif,image/jpg" /> </div> <div class="col-sm-10 col-sm-offset-1"> <span> </span> </div> <div class="col-sm-6 col-sm-offset-1"> <input type="button" @click="updateImg" value="修改头像"> <input type="button" value="取消"> </div> </div> <!--Vue--> data:function(){ return{ formData: new FormData(), imgs: {}, imgLen: 0, txtVal: 0, desc: "", } }, methods:{ updateImg:function(){ // console.log(this.imgs); //console.log(11); for (let key in this.imgs) { let name = key.split('?')[0]; //console.log(this.imgs[key]); this.formData.append(name, this.imgs[key]); } var self = this; var url = "../userAPI?action=updateUserImg"; this.$axios.post(url,self.formData).then(function(resp){ console.log(resp.data); if(resp.data.code==='0'){ //跳转登录页面 parent.layer.msg(resp.data.msg, { btn : [ '确定' ], //按钮 shade : false //不显示遮罩 }, function() { top.location.replace("index.jsp"); }); }else if(resp.data.code==='1'){ //跳转登录页面 parent.layer.msg(resp.data.msg, { btn : [ '确定' ], //按钮 shade : false //不显示遮罩 }); } }); }, //当图片改变时 addImg(event) { let inputDOM = this.$refs.inputer; // 通过DOM取文件数据 this.fil = inputDOM.files; console.log(inputDOM.files) let oldLen = this.imgLen; for (let i = 0; i < this.fil.length; i++) { let size = Math.floor(this.fil[i].size / 1024); if (size > 5 * 1024 * 1024) { alert('请选择5M以内的图片!'); return false } this.imgLen++; this.$set(this.imgs, this.fil[i].name + '?' + new Date().getTime() + i, this.fil[i]); //console.log(this.imgs); } } }
后台代码,用文件上传的插件
// 编码:SmartUpload获取的文件用的是GBK; // 创建一个上传对象 SmartUpload upload = new SmartUpload(); // 初始化对象 upload.initialize(getServletConfig(), req, resp); // 设置上传的基本设置 // 设置允许的上传文件列表 upload.setAllowedFilesList("jpg,png"); // 设置允许上传的单一文件的最大值,单位是字节; upload.setMaxFileSize(2 * 1024 * 1024); // 设置一次性允许上传的多个文件的总共大小1024=1k upload.setTotalMaxFileSize(10 * 1024 * 1024); try { // 设置禁止上传的文件的列表 upload.setDeniedFilesList("exe,com,bat"); // 执行上传文件 upload.upload(); // 获取上传的所有文件 Files files = upload.getFiles(); // 通过getCount()获取总数;进行遍历; for (int i = 0; i < files.getCount(); i++) { // 遍历判断获取客户端上传的文件 File file = files.getFile(i); if (file.isMissing()) {// 如果文件不存在 continue;// 不存在就不用处理 } // 获取上传的文件夹的位置;(项目的发布路径) String contexPath = req.getSession().getServletContext().getRealPath("/"); // 到服务器发布的时候改成服务器的路径 String path = "E:\\develop\\eclipse-workspace\\gzsxtgpcs-vue\\WebContent\\sqlImage"; // 输出控制台查看项目的发布路径 System.out.println(path); // 获取上传的文件的文件名.同时修改编码方式; String filename = new String(file.getFilePathName().getBytes(), "utf-8"); // System.out.println("文件名:" + filename); // 保存到数据库的路径 String img = "/sqlImage/" + System.currentTimeMillis() + ".jpg"; System.out.println(img); // 使用原文件名保存文件; file.saveAs(path + "/" + System.currentTimeMillis() + ".jpg"); // 从session中获取当前用户id HttpSession session = req.getSession(); User user = (User) session.getAttribute("user"); // 调用servce层的方法 ResponseMsg respMsg = null; if (user != null) { int row = userService.updateUserImg(user.getU_id(), img); if (row > 0) { user = userService.selectUserById(user.getU_id()); session.setAttribute("user", user); respMsg = new ResponseMsg("0", "修改成功"); } else { respMsg = new ResponseMsg("1", "修改失败"); } } String json = JSON.toJSONString(respMsg); resp.getWriter().append(json); } // 使用smartupload的request对象去获取字符内容; // 因为form表单传过来的是字节流,不是字符流了; Request request = upload.getRequest(); // String username=new String(request.getParameter("username"). // getBytes(),"utf-8"); // System.out.println(username+"****"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }
9.vue分页功能
前端代码:
<!-- 分页 start --> <div class="row"> <div class="col-sm-7 col-sm-offset-3"> <b>当前第 <button class=" btn-white active">{{currentPage }}</button>页 </b> <button class="btn btn-white" @click="getGoods(1,size)" v-show="currentPage!=1">首页</button> <div class="btn-group"> <!-- 上一页 --> <button type="button" class="btn btn-white" @click="getGoods(currentPage-1,size)" v-show="currentPage!=1"> <i class="fa fa-chevron-left"></i> </button> <!-- 页数 --> <button class="btn btn-warning" v-for="num in pages" v-if="num==currentPage" @click="getGoods(num,size)">{{num}}</button> <button class="btn btn-white" v-else @click="getGoods(num,size)">{{num}}</button> <!-- 下一页 --> <button type="button" class="btn btn-white" @click="getGoods(currentPage+1,size)" v-show="currentPage!=countPage.length"> <i class="fa fa-chevron-right"></i> </button> </div> <button class="btn btn-white" @click="getGoods(countPage.length,size)" v-show="currentPage!=countPage.length">尾页</button> <b>共 <button class="btn-info">{{countPage.length}}</button>页 </b> </div> </div> <!-- 分页 end -->
js代码:
return { goodsName : "", currentPage : 1,//当前页 size : 2, goodClassArr : [], countPage : 0,//总页数 }
computed:{ //分页,分为5页码,当点击3的时候还是1跟5,当点击4的时候为2跟6了 pages:function(){ //设置左边有什么 var left = 1; //设置右边有什么,默认是总页数 var right = this.countPage; //存放的数组 var arr = []; //当前页 var current = this.currentPage; //总页数 var all = this.countPage; //判断需要分为多少页 if(all >= 5){ //如何当前页大于3了并且当前页小于总页-1了 if(current > 3 && current < all-1 ){ //将当前页-2赋给左边 left =current- 2; right = current + 2; }else{ //判断当前页小于3时 if(current<=3){ left = 1; right = 5; }else{ //大于3时 left = all-4; right = all; } } } //循环得到左边有什么,右边有什么 while(left<=right){ arr.push(left); left++; } return arr; } }
10.a标签携带参数传递到另一个页面时
<a :href="'goodsDetails.html?gc_id='+goodClass.gc_id">
//获取a标签携带的参数 function getParameter(){ var url = location.href; console.log("aaa----"+url); var idx = url.indexOf("?"); if(idx==-1)return; var querystr = url.substr(idx+1); var arr = querystr.split("="); return arr; } var parameter = getParameter(); var gc_id = parameter[1];
11.js保留小数点后两位有效数字不四舍五入
return Math.floor(1.522222*100)/100;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!