remjs
引入该js以后 100px就是1rem 自动帮我们转换计算
例如:
UI出图写的是 500px 600px
那么实际写的是:5rem 6rem
<script src="js/rem.js"></script>
swiper
初步使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="swiper.js"></script>
<link rel="stylesheet" href="swiper.css">
<style>
.swiper-container{
width: 500px;
height: 300px;
margin: 50px auto;
border: 1px solid #000;
}
.swiper-slide{
text-align: center;
background-color: hotpink;
line-height: 300px;
font-size: 60px;
}
</style>
</head>
<body>
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">第一页</div>
<div class="swiper-slide">第二页</div>
<div class="swiper-slide">第三页</div>
<div class="swiper-slide">第四页</div>
<div class="swiper-slide">第五页</div>
</div>
<div class="swiper-pagination"></div>
</div>
<script>
var swiper=new Swiper(".swiper-container",{
//一些配置属性 在下边
pagination:{
el:".swiper-pagination",
//有焦点图点击的效果
clickable:true
}
});
</script>
</body>
</html>
是否自动播放 autoplay:true
自由滑动模式 freeMode:true
鼠标操作后自动效果消失解决 autoplayDisableOnInteraction: false
autoplay:{
delay:1000,
//补充 自动轮播开启 鼠标操作后自动轮播效果消失的解决:
disableOnInteraction:false,
}
无缝轮播模式 loop:true
方向设置 vertical horizontal direction:"vertical"
slide之间的间隔 spaceBetween:60
slide分组显示 一个页面显示几个slide slidesPerView:2
auto表示自适应 slidesPerView:'auto',
有焦点图点击的效果 pagination:{
el:".swiper-pagination",
clickable:true }
滚动条 scrollbar:{
el:".swiper-scrollbar",
// 过指定时间不滑动 则默认隐藏
hide:true, }
slide居中显示 而非靠左 centeredSlides:false
slide多行显示 slidesPerColumn:3
移动端没效果 没有光标 鼠标抓手样式 grabCursor:true
左右切换
<!-- 修改箭头颜色示范 -->
<div class="swiper-button-next swiper-button-white"></div> <!-- 白色 -->
<div class="swiper-button-prev swiper-button-black"></div> <!-- 黑色 -->
//左右切换
navigation:{
nextEl:".swiper-button-next",
prevEl:".swiper-button-prev",
}
渐变切换效果 effect:'fade'
方块切换效果 effect:'cube'
覆盖流效果 effect:'coverflow',
coverflow:{
//旋转 角度
rotate:50,
// 拉伸度
stretch:0,
// 深度
depth:100,
// 表示上面三个属性的强度 值越大 上面效果越明显
modifier:1,
slideShadows:true
}
3D翻转效果 effect: 'flip'
zepto 移动端的jq使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
#box{
width: 400px;
height: 400px;
background-color: hotpink;
}
</style>
</head>
<body>
<button>淡入淡出动画</button>
<div id="box"></div>
<script src="js/zepto.js"></script>
<script src="js/fx.js"></script>
<script src="js/touch.js"></script>
<script>
$(function () {
/*$("#box").click(function () {
// alert("点我干嘛?");
let per={
name:"小琪琪请那个",
age:16
};
let o={
location:"文化大厦"
};
//对象合并
console.log($.extend(per, o));
});*/
/*
zepto默认只具有 JQ的$选择器 dom功能
至于其他的 需要单独下载
比如动画的 fx.js
触摸时间的 touch.js
*/
$("button").click(function () {
//没有原来的 show hide fade slide 动画
// $("#box").fadeTo(0.4,1000);
// console.log($("#box").animate);
// console.log($("#box").swipe);
/* $("#box").animate({
opacity:0.3
},2000)*/
})
$("#box").swipe(function () {
alert("swipe了")
})
})
</script>
</body>
</html>
vue3.0+安装
1.打开cmd 输入命令 cnpm/npm install @vue/cli -g
2.vue -V查看版本
搭建项目
1.找一个文件夹输入命令 vue create 项目名称
开始调查问卷的方式创建项目:
1.Please pick a preset:
default (babel, eslint) 使用默认的babel(es6编译器) eslint(严格工具)
Manually select features 手动选择配置项 (选这个)
2.? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to invert selection)
>(*) Babel (es6编译器)
( ) TypeScript (一个跟js很像的 脚本语言)
( ) Progressive Web App (PWA) Support (Web APP支持 暂时不用)
(*) Router (Vue-router)
(*) Vuex (状态管理仓库)
(*) CSS Pre-processors (css预编译 sass less)
() Linter / Formatter (代码风格、格式校验) 格式校验工具
( ) Unit Testing (单元测试)
( ) E2E Testing (端对端测试)
上下选择 空格添加* 表示选中 回车 下一步
3.Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)
n 就是 默认的hash
4.Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)
Sass/SCSS (with dart-sass)
Sass/SCSS (with node-sass)
Less
Stylus
选择 css预编译的框架 sass less Stylus
5.? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
> In dedicated config files
In package.json
本次所选择的配置保存的位置在哪?
In dedicated config files 单独的配置文件
In package.json 在package.json文件里面保存
6.Save this as a preset for future projects? (y/N)
当前所选的配置套餐 是否保存 为了将来能够快速选择
项目启动:
命令: npm run serve
PC端和移动端自适应框架搭建
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import App_Mobile from "./App_Mobile";
import App_PC from "./App_PC";
let template="<App/>";
const reg=new RegExp(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i);
if(reg.test(navigator.userAgent)) {
template="<App_Mobile/>"
}else {
template="<App_PC/>"
}
/* eslint-disable no-new */
const vm =new Vue({
el: '#app',
components: { App ,App_Mobile,App_PC},
template,
})
Vuex
vuex中,有默认的五种基本的对象:
state:存储状态(变量)
getters:对数据获取之前的再次编译,可以理解为state的计算属性。我们在组件中使用 $sotre.getters.fun()
mutations:修改状态,并且是同步的。在组件中使用$store.commit('',params)。这个和我们组件中的自定义事件类似。
actions:异步操作。在组件中使用是$store.dispath('')
modules:store的子模块,为了开发大型项目,方便状态管理而使用的。这里我们就不解释了,用起来和上面的一样。
配置步骤:
1.cnpm install vuex --save
2.在src文件夹下面创建一个store文件夹(潜规则) 里面创建js文件
3. 在js文件里面 引入vue 引入vuex vue.use(vuex)
这样vue对象就有了一个 $store属性
4.new new Vuex.Store 对外导出这个对象
5. 在main.js引入vuex配置的js文件 在vue里面注册
使用步骤
使用步骤:
vuex包含五个属性
store用来声明变量 mutation用来 修改变量的值
在组件中获取vuex变量的值:
this.$store.state.变量名
修改vuex指定变量的值:
需要通过mutations里面的方法进行修改
调用mutations里面的方法:
this.$store.commmit("mutaions里面的一个方法名",这个方法的第二个参数)
vuex中存储的数据 一旦刷新 则会回归默认值
其实vuex的本质 就是相当于搞了一个全局的data 数据仓库
优点:
全局所有组件都可以进行存取 数据传输很方便 很轻松实现组件之间的传参
缺点:
页面刷新以后 数据回归默认值
vuex比较重 一般会出现在大型项目中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state:{
str:"我是str变量的值"
},
mutations:{
// 这里面都是一个个方法 每一个方法都是针对某一个state变量的修改方法
//参数1: 是state对象,参数2 就是要修改的新值
setStr(state,newVal){
state.str=newVal;
}
}
})
<template>
<div>
我是首页
<p>
<input type="text" v-model="msg">
<button @click="setstr">给str修改值</button>
<button @click="getstr">获取str的值</button>
</p>
</div>
</template>
<script>
export default {
name: "Home",
data(){
return{
msg:""
}
},
methods:{
setstr(){
// 通过commit方法 调用mutations里面的一个方法 修改str的值
this.$store.commit("setStr",this.msg);
},
getstr(){
// 获取vux里面变量的值
console.log(this.$store.state.str);
}
}
}
</script>
<style scoped>
</style>
<template>
<div>
我是个人中心
<p>
<button @click="getstr">获取str的值</button>
</p>
</div>
</template>
<script>
export default {
name: "User",
methods:{
getstr(){
console.log(this.$store.state.str);
}
}
}
</script>
<style scoped>
</style>
event-bus
因为vuex比较重 大型项目会使用vuex 那么小一点的项目 会使用 event-bus
原理:
借助一个新的空vue对象 这个vue对象就单独提供data功能 实现全局的公用data就可以实现传参
vue对象本身有两个方法 $emit和 $on
$on是注册事件
$emit是触发这个事件 并传参
经过我们测试分析 $on是注册事件 必须是在$emit之前执行
也就是必须先注册事件才能提交事件
经过生命周期的测试
发现新页面组件的 beforeCreate,created,bedoreMount三个声明周期
在旧组件页面的 beforeDestroy生命周期之前执行
所以event-bus的使用:
在src里面一个store文件夹里面创建js文件
对外到处一个新的 new Vue()对象
import Vue from "vue"
export default new Vue();
在main.js文件里面引入这个空Vue对象
并通过原型绑定给当前Vue 全局可以使用this.$eventBus(自己起的名字)使用
import EventBus from './store'
Vue.prototype.$eventBus=EventBus;
在新组件的created里面 this.eventBus对象.$on("事件名称",驱动函数)
在旧组件的beforeDestroy生命周期里面 this.eventBus对象.$emit("on注册的那个事件名称",要传的参数)
template>
<div>
我是首页
<p>
<input type="text" v-model="msg" placeholder="再次输入要给购物车传的数据">
</p>
</div>
</template>
<script>
export default {
name: "Home",
data(){
return{
msg:""
}
},
methods:{
},
beforeDestroy() {
this.$eventBus.$emit("trigger_str",this.msg);
}
}
</script>
<style scoped>
</style>
event-bus传过来的数据 可以通过data里面的变量做中转 放到页面上使用
<template>
<div>
我是购物车页
<h1>{{msg}}</h1>
</div>
</template>
<script>
export default {
name: "Gwc",
created() {
// 注册event-bus事件
this.$eventBus.$on("trigger_str",(a)=>{
console.log("home传过来数据了:",a);
// console.log("去尝试拿data的数据:",this.msg);
this.msg="我是created里面修改的值"
}
);
},
methods:{
},
data(){
return{
msg:"我是msg默认数据"
}
}
}
</script>
<style scoped>
</style>
路由的导航钩子(全局路由守卫)
前置路由守卫
router.beforEach
在每一个路由即将跳转之前触发该方法的回调
后置路由守卫
router.afterEach
在每一个路由跳转之后触发该方法的回调
这两个方法的参数都是同样是
是一个回调
router.beforeEach(回调函数)
回调函数三个参数:
to:
本次路由要跳转的目标路由对象(就是那个 this.$route)
from:
本次路由从哪里跳转的源路由对象(就是那个 this.$route)
next:
是一个回调函数 next() 执行next方法 才会同意本次跳转
然后路由才会跳转
/* 之所以在这引入全局路由守卫 是因为需要用到vm这个vue对象 */
router.beforeEach((to,from,next)=>{
if(to.meta.auth){
// 如果需要登录 我们再判断是否已经登录
// 判断vuex中 是否已经登录了
if(vm.$store.state.isLogin.isLogin){
// 如果已经登录了 则直接跳转
next();
}else{
// 还未登陆 弹出提示框 并且跳转到登录页面
vm.$dialog.toast({
mes:"您还未登录,请登陆后尝试!",
timeout:1000,
icon:"error",
callback:()=>{
// next方法可以传入一个目标 其实就是原来的 push()
/* next({
path:"/login",
});
*/
// next("/login");
// vm.$router.push("/login")
// next();
// 如果是未登录状态 我们先去登录页 然后把 原本的目标传给登录页
vm.$router.push({
name:"Login",
params:{
// to就是原本目标的路由对象 path属性就是目标路由的路径
srcPath:to.path
}
})
}
})
}
}else{
// 如果不需要登录 则直接跳转
next();
}
});
仿iPhone进场动画
<template>
<div id="app">
<transition :name="trname">
<router-view class="Router"></router-view>
</transition>
</div>
</template>
<script>
/*
vue2.0本身使用动画的原理:
在想要实现动画效果的标签外面套上
transition标签
<transition name="trname">
<div>我是要实现动画的盒子</div>
</transition>
一旦定义了 transition标签 那么 name属性的名字最后就会被动态的添加到页面上去
有这么几个类名是最后动态生成的
trname-enter
当前动画盒子进入的那一瞬间 触发一下就完事 等盒子进入后移除
trname-enter-active
当前动画盒子从进入开始到结束一直 有这个类名 可以使用css的过渡进行监听 实现动画效果
过渡中一直有该类
trname-enter-to
当前动画盒子 进入后 enter消失时 to添加 等到盒子过渡完成 to消失
下面leave同理
trname-leave
trname-leave-active
trname-leave-to
向右移动translate(tx,0)和向左移动translate(-tx,0);
*/
export default {
name: 'App',
data(){
return{
// 用来定义动画名字的变量
trname:"tiao",
}
},
watch:{
/* 监听器函数的参数还是 新值和旧值
只不过本次监听的是路由对象
在路由对象中 所谓的新值 就是本次即将要跳转的目标路由对象
旧值就是当前正在展示马上要跳走的 原来路由对象
*/
"$route":{
handler(){
/* console.log(this);
console.log("路由变化了:"+this.$router.isBack); */
if(this.$router.isBack){
// 当前是回退
this.trname="back";
}else{
this.trname="tiao"
}
this.$router.isBack=false;
},
}
},
mounted(){
// this.$route 指的是当前App.vue这个组件的路由对象
//那么监听这个对象 也就表示 App.vue下面只要有路由变化就监听到
}
}
</script>
<style>
/* 当前路由被激活时触发这个类 下面的icon和 txt 都分别显示什么颜色 */
.router-link-active>.yd-tabbar-icon{
color:RGB(28,152,252);
}
.router-link-active>.yd-tabbar-txt{
color:RGB(28,152,252);
}
#app{
height: 100%;
width:100%;
}
body{
background:#fff;
}
.Router{
position: absolute;
width: 100%;
transition: all 1s ease;
}
/* .ww-enter,
.qq-leave-active {
opacity: 0;
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
.ww-leave-active,
.qq-enter {
opacity: 0;
-webkit-transform: translate(-100%, 0);
transform: translate(-100% 0);
}
*/
/* 如果页面跳转时执行这两个类名 ↓*/
.tiao-enter{ /*针对从右边即将要进来的屏幕*/
opacity: 0;
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
.tiao-leave-active{/* 针对当前正在展示 即将往左右离开的屏幕 */
opacity: 0;
-webkit-transform: translate(-100%, 0);
transform: translate(-100% 0);
}
/* 如果点击back键时 执行下面两个类名 */
.back-enter{
opacity: 0;
-webkit-transform: translate(-100%, 0);
transform: translate(-100% 0);
}
.back-leave-active{
opacity: 0;
-webkit-transform: translate(100%, 0);
transform: translate(100%, 0);
}
</style>