文章目录
- 使用gitHub进行版本控制
- 一、子组件与父组件通信
- 一点一、获取dom节点(html对象)
- 二、根据v-model双向绑定vue数据和html标签(复选框,单选框),可直接影响值
- 三、删除选中内容(使用filter函数将数组中满足条件的筛选出来)
- 四、全选与全不选(通过forEach方法遍历数组所有元素)
- 五、根据选中数量,动态显示数据(根据条件计算数组元素)
- 六、实现若所有复选框都选中,则全选按钮选中,若有一个没选中,则全选按钮自动不选中,不影响全选按钮功能(使用监听函数的get和set)
- 七、本地存储数据,Watch深度监听(JS函数介绍来源于==菜鸟教程==)
- 八、Ajax请求,使用vue2.x推荐的axios
- 九、SPA(单页面应用)前端路由,动态加载组件
- 十、触发事件跳转路由(this.$router.replace 或push(path)函数可跳转到指定路由)
- 十一、移动端滑动轮播(最外层定义一个div,你希望的轮播大小,里面一个宽度非常大的div,用来容纳图片,如果你有5个轮播图,那么这个div应该正好是最外层div的5倍)
- 十二、分模快构建路由(不同功能分离路由)
- 十三、ES6的Promise配合axios处理ajax的封装js
- 十四、封装交互接口
- 鼠标事件
- 十五、跳转路由,带有自己的激活样式
- 十六、事件传递当前节点
- 十七、操作style
- 十八、Vue强制刷新页面
- 十九、store操作
- 二十、深度监听,解决路由地址没变的情况下,数据无法动态刷新
- 二十一、跳转路由从新页面打开
- 二十二、vue网络请求会自动带上localhost:8080/
使用gitHub进行版本控制
- 1、生成本地仓库git init
一、子组件与父组件通信
1、子组件使用父组件的值
2、子组件通过父组件提供的函数,修改父组件的数据
3、子组件与父组件方法同名,无限调用结果超出最大调用栈(一定要避免子组件函数与父组件传递来的函数同名)
一点一、获取dom节点(html对象)
二、根据v-model双向绑定vue数据和html标签(复选框,单选框),可直接影响值
三、删除选中内容(使用filter函数将数组中满足条件的筛选出来)
四、全选与全不选(通过forEach方法遍历数组所有元素)
五、根据选中数量,动态显示数据(根据条件计算数组元素)
Array.reduce(function(total,item){
if(item.flag==true) return total+1;
else return total;
},functionItem)
* total:初始值和返回值,默认Object,在整个执行过程中,值不会丢失
* item:当前数组元素
* functionItem:回调函数初始值,初次调用将值赋值给total,之后不会作用
* 回调函数执行次数和数组元素数量相同,functionItem会在第一次调用时赋值给total,total会根据函数体做出相应改变,最终total是整个函数返回值
return this.items.reduce((total,item)=>item.flag==true?total+1:total,0);
六、实现若所有复选框都选中,则全选按钮选中,若有一个没选中,则全选按钮自动不选中,不影响全选按钮功能(使用监听函数的get和set)
- 需要了解,这里的计算属性我双向绑定在复选框上,它操作的仅仅是复选框是否勾选上,也就是说与全选功能分离开了,互相不影响,而对于这里的set,有没有都一样,只是语法要求这样写,而input上绑定了click事件用于实现全选功能,不会影响与被影响
- 点击事件如下:需要说明,这里假设没有全选,计算变量的值就是false,而我们现在想让它全选,点击后并不会改值,所有需要传相反的值过去,而传过去后,所有都被选中,num就变为数组长度,这时计算属性也就根据监听条件变成了true
七、本地存储数据,Watch深度监听(JS函数介绍来源于菜鸟教程)
-
使用Js原生函数Window localStorage 属性
localStorage 可以创建一个本地存储的 name/value 对
保存数据语法: window.localStorage.setItem("key", "value"); 读取数据语法:返回值为字符串 var lastname =window.localStorage.getItem("key"); 删除数据语法: window.localStorage.removeItem("key");
JSON.parse() 方法用于将一个 JSON 字符串转换为对象。
JSON.parse(text[, reviver]) 参数说明: text:必需, 一个有效的 JSON 字符串。 reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。
JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。
语法 JSON.stringify(value[, replacer[, space]]) 参数说明: value: 必需, 要转换的 JavaScript 值(通常为对象或数组)。 replacer: 可选。用于转换结果的函数或数组。 如果 replacer 为函数,则 JSON.stringify 将调用该函数,并传入每个成员的键和值。使用返回值而不是原始值。如果此函数返回 undefined,则排除成员。根对象的键是一个空字符串:""。 如果 replacer 是一个数组,则仅转换该数组中具有键值的成员。成员的转换顺序与键在数组中的顺序一样。 space: 可选,文本添加缩进、空格和换行符,如果 space 是一个数字,则返回值文本在每个级别缩进指定数目的空格,如果 space 大于 10,则文本缩进 10 个空格。space 也可以使用非数字,如:\t。
-
1、将写死的数据,清除,使用localStorage 动态将本地文件存储到数据中(这里items是个数组,但计算机不知道,所以在localStorage没有值的情况下,存储一个空数组,JSON.parse参数是字符串,所以写’[]’)
-
2、深度监视数据
八、Ajax请求,使用vue2.x推荐的axios
- 安装axios:命令npm install axios --save
- 引入模块并使用
九、SPA(单页面应用)前端路由,动态加载组件
- 1、创建普通vue-cli文件,然后用npm创建过程中引入Router路由,或者用命令安装路由npm install vue-router --save
- 2、src文件夹下创建router文件夹(路由文件都在这里名存放),然后在其中创建一个index.js文件
- 3、在主文件main.js配置路由
- 4、写一个小案例
- 效果演示
- 1、创建路由组件(因为一共两个选项卡,移入不同选项卡,会生成不同组件,所以有对应两个路由)
- 2、将这两个组件添加到路由
- 3、在父组件引入路由组件
嵌套路由(一个路由嵌套多个子路由)
- 1、定义子路由组件
- 2、注册子组件
- 3、在父路由中,使用子路由
- 测试
路由默认重定向,当转到特定路由组件,直接显示默认内容,而不需要选中才出现(注意,每次请求都只生效一次)
- 1、定义重定向
切换路由时,不结束刷新路由生命周期,保留数据
- 使用keep-alive标签套住的view,切换路由时,不会刷新数据
路由组件传值
- 1、先在路由的路径中声明参数
- 2、使用名字+params传值
根据url参数动态展示路由数据
通过router-view标签传递参数
十、触发事件跳转路由(this.$router.replace 或push(path)函数可跳转到指定路由)
十一、移动端滑动轮播(最外层定义一个div,你希望的轮播大小,里面一个宽度非常大的div,用来容纳图片,如果你有5个轮播图,那么这个div应该正好是最外层div的5倍)
- 1、创建文档结构
- 2、编写css
- 效果
- 之后就是实现效果,但是怎么实现循环呢?我们可以每次把最后一张轮播复制一份放在最前面,最前面的复制一份放在最后面,当我们在第一张图片往左滑动时,直接就转到复制的最后一张上,然后迅速转移到真正的最后一张,用户看不出来我们这样切换,就实现了循环
- 但是这样就将代码写死了,所以我们应该用js或vue代码实现动态轮播
vue实现动态轮播
- 1、给轮播容器(最大的内个div)添加ref属性
- 2、获取dom节点,并由它获取子节点,然后插入
/* 获取节点*/
const routers_wapper =this.$refs.routers_wapper;//获取轮播容器
const first = routers_wapper.firstChild; //获取轮播容器中第一个子节点
const last = routers_wapper.lastChild; //获取轮播容器中最后一个子节点
/* 拷贝节点 */
const firstClone =first.cloneNode(true); //获取first的精确拷贝,属于复制一份,如果不拷贝,相当于剪切操作
const lastClone =last.cloneNode(true); //获取last的精确拷贝,包括所有属性
/* 将拷贝的第一个节点放在最后,拷贝的最后一个节点放在最前面*/
routers_wapper.appendChild(firstClone); //在最末尾添加一个first(刚刚获取的最前面的节点)
//insertBefore可以在当前容器中的指定元素之前插入一个元素
routers_wapper.insertBefore(lastClone,first); //在first元素之前插入last的拷贝
/* 1、修改页面样式结构 */
/* 获取节点*/
const routers=document.querySelector('div.routers');//获取总容器
const routers_wapper =this.$refs.routers_wapper;//获取轮播容器
const first = routers_wapper.firstChild; //获取轮播容器中第一个子节点
const last = routers_wapper.lastChild; //获取轮播容器中最后一个子节点
/* 拷贝节点 */
const firstClone =first.cloneNode(true); //获取first的精确拷贝,属于复制一份,如果不拷贝,相当于剪切操作
const lastClone =last.cloneNode(true); //获取last的精确拷贝,包括所有属性
/* 将拷贝的第一个节点放在最后,拷贝的最后一个节点放在最前面*/
routers_wapper.appendChild(firstClone); //在最末尾添加一个first(刚刚获取的最前面的节点)
//insertBefore可以在当前容器中的指定元素之前插入一个元素
routers_wapper.insertBefore(lastClone,first); //在first元素之前插入last的拷贝
/* 2、设置样式 轮播容器宽度等于 总容器宽度*轮播内容数量 */
/* 获取容器中所有轮播div节点 */
const routerArr=routers_wapper.querySelectorAll('div.router');//获取轮播容器中class为router的div
let index=1;//表示当前轮播索引值
/* 获取routers的宽度,此参数需要做变换,声明为let */
let routersWidth=routers.offsetWidth;
/* 获取轮播div的数量 */
const routerNumber=routerArr.length;
/* 动态设置轮播容器宽度 */
routers_wapper.style.width=routersWidth*routerNumber+'px';
/* 动态设置每一个轮播内容的宽度(它们的宽度就是总容器的宽度)*/
routerArr.forEach(item=> routersWidth+'px')
/* 3、设置默认偏移(要偏移轮播容器,显示第一张图片,而不是我们插入的最后一张的拷贝)而偏移就是总容器宽度*/
routers_wapper.style.left=-routersWidth+'px';
/* 4、我们必须保证 当切换不同屏幕时,图片的大小也相应变化,也就是响应式*/
window.onresize=function(){//监听屏幕是否改变大小
/* 重新获取routers的宽度 */
routersWidth=routers.offsetWidth;
/* 重新动态设置轮播容器宽度 */
routers_wapper.style.width=routersWidth*routerNumber+'px';
/* 重新动态设置每一个轮播内容的宽度(它们的宽度就是总容器的宽度)*/
routerArr.forEach(item=> routersWidth+'px')
/* 重新设置默认偏移(要偏移轮播容器,显示第一张图片,而不是我们插入的最后一张的拷贝)而偏移就是总容器宽度,当我们正在轮播时,应该根据
当前的轮播内容设置默认偏移,所以*index
*/
routers_wapper.style.left=-(index*routersWidth)+'px';
};
/* 5、实现自动轮播 */
setInterval(()=>{//时钟,每秒触发一次
routers_wapper.style.transition="0.5s"//过渡为0.5s
index++;
routers_wapper.style.left=-(routersWidth*index)+'px';//重新根据下标,计算偏移
if(index>=routerNumber){//如果滚到最后一张图片,瞬间将下标切换到第一张
index=1;
routers_wapper.style.transition="none"//这里不能有过渡效果,因为要让用户看不出来,瞬间切换
routers_wapper.style.left=-(routersWidth*index)+'px';//根据下标计算偏移
}
},1000);
/* 6、实现手指滑动*/
let startX,startY,moveX,moveY;/* 开始时的坐标,移动时的坐标,结束时的坐标 */
let distanceX,distanceY;/* 用来记录坐标直接的差异 */
/* 添加开始触摸监听事件*/
routers.addEventListener('touchstart',(e)=>{
/* 获取第一个手指对象的触屏坐标*/
startX=e.targetTouches[0].clientX;
startY=e.targetTouches[0].clientY;
});
/* 添加滑动事件*/
routers.addEventListener('touchmove',(e)=>{
/* 获取每次滑动的触屏坐标*/
moveX=e.targetTouches[0].clientX;
moveY=e.targetTouches[0].clientY;
/* 计算与开始坐标的差异*/
distanceX=moveX-startX;
distanceY=moveY-startY;
/* 设置偏移*/
if(distanceY<0 && Math.abs(distanceY)>=50){
this.routersFlag=true;
}
else if(distanceY>0 && Math.abs(distanceY)>=50){
this.routersFlag=false;
}
})
/* 添加结束触摸事件*/
routers.addEventListener('touchend',(e=>{
if(distanceX<0 && Math.abs(distanceX)>=50){
index++
if(index===routerNumber-1){
routers_wapper.style.left=-(index*routersWidth)+'px';
routers_wapper.style.transition="none";
index=1;
routers_wapper.style.left=-(index*routersWidth)+'px';
}
else{
routers_wapper.style.transition="0.5s";
routers_wapper.style.left=-(index*routersWidth)+'px';
}
}
else if(distanceX>0 && Math.abs(distanceX)>=50){
routers_wapper.style.left=-((index-1)*routersWidth)+'px';
}
console.log(distanceX)
}));
十二、分模快构建路由(不同功能分离路由)
- 1、创建子路由文件,构建数组即可(路由主文件的主旨就是个数组)
- 2、index.js中添加子路由文件
- 3、子路由(如何构建子路由)
- 子模块路由如何重定向
十三、ES6的Promise配合axios处理ajax的封装js
Object.keys(Obj):返回一个由给定对象自身可枚举属性组成的数组
//数组
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// 对象
var obj = { key1: 'a', key2: 'b', key3: 'c' };
console.log(Object.keys(obj)); // console: ['key1', 'key2', 'key3']
stringObject.substring(start,stop): 方法用于提取字符串中介于start和stop两个指定下标之间的字符。
stringObject.lastIndexOf(str[,index]):方法可返回子串str在父串stringObject中最后出现的位置,在一个字符串中的指定位置从后向前搜索。
str:表示需要查找的子串
index:可选参数,指定从哪个下标开始,从后往前找,不指定就从最后一个找
/*
ajax请求封装
@param:
url:请求地址
data:请求参数
type:请求类型
return:Promise对象
*/
import axios from 'axios'
export default function ajax(url,data={},type='GET'){
/*
Promise用来处理ajax请求问题,有3个状态,Pending(进行中)、Resolved(已完成)、Rejected(已失败)
3个状态都是根据ajax请求结果而决定
*/
return new Promise(function(resolve,reject){
/* 1、执行异步*/
let promise;
if(type==='GET')
{
let dataStr='';//存储用data数据拼接成字符串
Object.keys(data).forEach(key=>{//将data中的key遍历成一个新数组,然后循环遍历key,根据key将data中数据拼接成字符串
dataStr+=key+'='+data[key]+'&';//将data中数据都以json的格式拼接到dataStr中,末尾用&,是为了标识结尾
});
if(dataStr !=''){
dataStr=dataStr.substring(0,dataStr.lastIndexOf('&'));
url=url+'?'+dataStr;
}
//发送ajax请求
promise=axios.get(url);
}else{
//发送post请求
promise=axios.post(url,data);
}
promise.then(function(response){
/* 2、请求成功,执行resolve()*/
resolve("session");
}).catch(function(error){
/* 3、请求失败,执行reject()*/
reject('error');
});
})
}
十四、封装交互接口
/* 接口请求封装模块
所有接口用req开头
接口基本用ajax和后台进行交互
所以所有接口都用固定模板
*/
import ajax from './ajax.js'
/* 1、根据经纬度获取位置详情 */
export function reqAddress(geohash)=>ajax(`/position/${geohash}`);
/* 2、获取食品分类列表 */
export function reqFoodTypes=()=>ajax('/index_category');
/* 3、根据经纬度获取商铺列表 */
/* 这里参数传递用的是ES6语法,longitude:longitude 可以简写成longitude 而传入b,后台规定参数名字为latitude,就得写出latitude:b */
export function reqFoodTypes=(longitude,b)=>ajax('/shop',{longitude,latitude:b});
/* 4、根据经纬度和关键字搜索商铺列表 */
/* 5、获取一次性验证码 */
/* 6、用户名密码登陆 */
/* 7、发送短信验证码 */
/* 8、手机号验证码登陆 */
/* 9、根据会话获取用户信息 */
/* 10、用户登出 */
鼠标事件
@mousedown:当用户单击鼠标按钮而元素有焦点时触发。
@mousemove:当鼠标移动而指针指向元素时触发。
@mouseout:当鼠标指针离开元素时触发。
@mouseover:当鼠标指针移动到元素上时触发。
@mouseup:当元素有焦点时,用户释放鼠标按钮时触发。
@mousewheel:当用户旋转鼠标滚轮而元素有焦点时触发。
@mouseenter:当鼠标指针进入元素时触发。这俩在元素中,移动到子元素上不会失去焦点
@mouseleave:当鼠标指针离开元素时触发。
动态添加事件为 <button> 元素添加点击事件。 当用户点击按钮时,在 id="demo" 的 <p> 元素上输出 "Hello World" :
document.getElementById("myBtn").addEventListener("click", function(){
document.getElementById("demo").innerHTML = "Hello World";
});
十五、跳转路由,带有自己的激活样式
<router-link to="/" tag="a" active-class="current" exact>首页</router-link>
active-class:当前路由激活时的样式
exact:避免选择其它路由时,当前路由的激活样式还在
十六、事件传递当前节点
<a href="javascript:;" @click="getChildren($event,item,0)">{{item.title}}</a>
$event是点击对象,
getChildren(e,item,index){//e是当前点击元素,item是每一个课程分类对象,index是层级,0表示根层级
console.log(e.target)
e.target.style.color="red";
e.target 是当前点击元素
十七、操作style
<div class="L-c-form" :style="{'display':(!activeFlag?'block':'none')}">
</div>
十八、Vue强制刷新页面
this.$router.go(0)//强制刷新页面
组件刷新有v-if和改变:key的值两种方法
十九、store操作
store文件代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
input:"",//全局搜索关键字
publicSearchFlag:true,//全局搜索true表示搜索课程名,false表示搜索讲师名
publicSearchWatch:true,//全局搜索监听函数,解决相同路由点击搜索按钮不刷新的问题
token:localStorage.getItem("token"),//全局存放token,这里直接通过localSrotage获取,这样就省去了get的过程
userInfo:JSON.parse(sessionStorage.getItem("userInfo")),//全局存放用户信息,通过JSON反序列化,将用户数据拿到
loginFlag:false,//用来标识当前登录状态,false表示没有登陆
},
mutations: {//这个就相当于java的set方法
SET_TOKEN:(state,token)=>{//设置值到token
state.token=token;
localStorage.setItem("token",token);//将token存储到localStorage中,就是存储在客户端
},
SET_USERINFO:(state,userInfo)=>{//设置用户信息
state.userInfo=userInfo;
sessionStorage.setItem("userInfo",JSON.stringify(userInfo));//将用户信息存放到session会话中,这个方法不能穿对象,所以通过JSON序列化
},
SET_LOFIN_Flag:(state,loginFlag)=>{//设置登陆状态
state.loginFlag=loginFlag;
},
SET_LOGOUT:(state)=>{//退出时,清除所有数据
state.token='';
state.userInfo={};
state.loginFlag=false;
state.avatar='';
localStorage.setItem("token",'');
localStorage.setItem("Access-Token",'');
sessionStorage.setItem("userInfo",JSON.stringify(''));
}
},
getters:{
//get
getUserInfo:state=>{
return state.userInfo
},
getToken:state=>{
return state.token
}
},
actions: {
},
modules: {
}
})
store设置值,获取值
this.$store.commit("SET_USERINFO",response.data);//通过set方法设置值
this.$store.getters.getUserInfo//通过get方法获取值
this.$store.state.publicSearchFlag//通过state获取
二十、深度监听,解决路由地址没变的情况下,数据无法动态刷新
二十一、跳转路由从新页面打开
用这个语句代替this.$router.push等跳转语句即可
let routeData = this.$router.resolve({
name: "Player",
query: {courseId:this.$route.query.courseId,minutiaName},
params:{id:videoPath}
});
window.open(routeData.href, '_blank')
二十二、vue网络请求会自动带上localhost:8080/
直接写会默认带上localhost
192.168.10.105:8888/
需要加上协议http://
http://192.168.10.105:8888/