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: {
                deeptrue,
                handlerfunction (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 @   站着说话不腰疼  阅读(66)  评论(0编辑  收藏  举报
编辑推荐:
· 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 重磅开源!
点击右上角即可分享
微信分享提示