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

语法分为两种;

  1. 不是表单请求的方式,是一个json字符串的方式来提交数据的

    1. 不可以用getParameter();来接收数据

    2. 语法:

    3. 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);
      
  2. 表单类型的数据:

    1. 语法

      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>&nbsp;</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>&nbsp;&nbsp;&nbsp;&nbsp;
									<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;

posted @ 2022-03-10 09:33  站着说话不腰疼  阅读(74)  评论(0)    收藏  举报