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;

浙公网安备 33010602011771号