计算属性 监听
- methods 里面用来设置方法 在模板得表达式里使用这个方法 '{{}}'
双向数据绑定
v-modul
v-on dom事件绑定类型 简写为 @
组件开发
先写组件 可以高效
-
1.创建组件
let component =Vue.extend({
<template></template>
})
2.注册组件Vue.component('hehe',component)
3.使用组件
//使用组件 把组件名当作标签名来用
全局组件 与局部组件
-
- 全局组件 通过Vue.component 注册的组件都是全局组件
- 局部组件 注册在实例的内部
在new Vue ({
components:{ 'hehe':component }
})
- 组件的简写
- Vue.component('hehe',{
template:'<组件模板名>
})
- 组件模板
<template>
<div id="tp1">
</div>
</template>
template 只能有一个根元素
-
组件里的date 是一个对象
data(){
return{
name:'韩梅梅'
}}
- 全局组件嵌套
- 组件里套组件
- 父组件嵌套子组件 把子组件的模板放在父组件里面
-
局部组件的嵌套
- components:{
'Fa':{
template:"#fa",
components:{
'Son':{template:'#son'}
}
},
}
- components:{
- 然后在父组件里使用子组件就可以了
- 局部组件里有固定的关系
组件里的通信
+ 自定义属性 <son hehe='123' ></son>
props 可以通过用来传递参数,可以传递多个 props:['hehe','age']
- 父组件可以通过将自己的数据通过props 自定义属性传递子组件
- props 的数据对于子组件来说只能使用不能修改
生命周期
beforeCreate 可以数据请求
createted 可以数据请求 可以修改数据
beforeMount 可以数据请求 可以修改数据
mounted dom的初始化操作
-
beforeUpdate 数据修改的时候触发 dom 是修改之前 注意修改数据死循环
- updated 数据修改的时候触发 dom 是修改之后 注意修改数据死循环
beforeDestory 组件销毁卸载的时候触发 能获得dom 擦屁股 全局事件监听 全局计时器
destoryed 组件销毁卸载的时候触发 没有dom 擦屁股 全局事件监听 全局计时器
过滤器
全局过滤器 Vue.filter('name',处理函数)
-
局部过滤器 组件里注册 template:'',
components:'',
filters:{
"name" :()=>{} }
- 监听 watch 监听某一个数据的改变 dom数据是修改前的数据
-
是一个对象 watch:{
监听的数据:(newvalue,oldvalue)=>{ console.log('数据变了') } }
- 计算属性
- computed 计算属性 可以和data里的数据进行关联 得到一个新的数据
指令
npm run serve 本地开发环境启动
npm run build 编译打包 (使用的是webpack 打包)打包后的路径为绝对路径
main.js 为vue项目的入口组件
-
App.vue 单文件组件
-
组件的组成
模板: <template>-
<div>
<div>
</div>
-
</template>
<script>
export default {
data(){
return {
数据
}
},
methods:{
方法
},
}
</script>
<style>
</style>- 使用import App from './App.vue' 来引入组件
-
-
组件嵌套
想在哪里引入组件 就在那个组件里使用 类似 “import App from './App.vue'”引入组件
然后在export defaul 里使用 components:{"组件名","给使用在页面相当于标签名的起名字"} 注册组件
spa(单页面应用) mpa(多页面应用)
- vue就是使用的单页面应用
- seo 搜索引擎优化
- 优点:页面切换流畅 组件的切换
组件开发 组件复用可以提高开发效率
缺点:首屏加载过慢
seo优化不好
tower
- 项目开发的成员增加及任务分配
项目开发
- 如何控制组件的切换
- 动态组件
- 路由
-
动态组件 控制组件的切换
- 动态组件 is属性
<component :is='"state"?"xixi":"hehe"'></component>
可以使用所有的标签 不一定是component
- 动态组件 is属性
路由 重点
1.在router里的index.js 引入
2.根据地址栏的改变来控制组件的切换
-
3.原理:监听地址栏的改变
根据地址栏的变化匹配路由表渲染不同的的组件
安装路由模块 npm install vue-router<router-link to="/home"></router-link> 控制地址栏的改变
<router-link> 默认渲染为a标签 通过tag 来改变样式 例如 tag="li" 渲染为li
<router-view></router-view> 是一个容器 来渲染组件
a. 配置路由表
1.引入vue import Vue from 'vue'
2.引入路由 import Router from 'vue-router'
3.在vue中使用路由 Vue.use(Router)
4.创建路由对象 let router=new Router({
routes:[
{
path:"/home", 12
component:Home
},
{
path:"/Singer",
component:Singer
}
]
})
5.抛出路由 export default router
b. 在实例中注册路由
- 在main.js 中 引入组件 import router from "./router/index.js'
- 在 new Vue 中写入 'router'
c. 在根组件里App.vue 中写上 <router-link to="/home"></router-link>
<router-link to="/singer"></router-link>
实现地址栏改变
d. <router-view></router-view> 跳转到不同的页
重定向
-
path:'/',
redirect:'/home'默认根路径为 'home'
- 动态路由匹配
- path:'/singer/:hehe',
- ':' 表示在singer后面还需要添加一个变量才能跳到歌手页 随便什么变量都可以
- 动态路由匹配可以传参 通过params 传递参数
- 路由模式 hash #
history 打包后可能404 需要与后端配置完成
- active-class= 'sel' 给选中的当前页加类名
编程式导航 与 声明式导航
- 用标签的叫声明式导航 a标签 <router-link>也是
- 用js代码写的叫编程式导航 window.history.push=""
编程式导航
<button @click='jump("/home")'>首页</button>
-
<button @click='jump("/singer")'>歌手</button>
在methods:{
jump(path){
this.$router.push('/home')
}}
这段代码就能实现编程式导航 点击button实现组件的跳转
使用push 和replace的区别 页面栈
a=>b=>c=>d 使用push返回时会依次返回
使用replace返回 直接返回到第一层
路由传参
this.
router('/hehe')
-
命名路由 给 {
name:'Singer'
path:"/Singer",
component:Singer}
- 当路由的名字很长时,使用命名路由
this.$router.push({name:'rank'})同样可以跳转到组件
- 当路由的名字很长时,使用命名路由
- 三种路由传参方式
- 路由传参
- params this.$router.push({name:'rank',params:{us:123,ps:123}})
- query 传参 this.$router.push({name:'rank',query:{us:123,ps:123}})
- this.$router.push({path:'rank',query:{us:123,ps:123}})
- path 与params 不能一起用
嵌套路由
- 在需要嵌套的的组件(父组件)里写一个 <router-view></router-view>
- 在根组件里引入嵌套组件
- 在需要嵌套的组件里写一个children 注册组件
- {
path:'/my',
component:my,
children:[
{
path:'login',
component:Login
},
]
}
- 次级组件里不能使用"/" "/"表示根组件
- 可以有多个次级组件 一直嵌套
命名视图
- <router-view></router-view>
- <router-view name='a'></router-view>
- <router-view name='b'></router-view>
- 注册组件变为 components
- components:{
default:Rank, //默认的组件
a:Login,
b:Info
}
- 作用:同一个路由里渲染不同的组件
路由守卫 路由导航 路由拦截器
全局前置守卫
- 所有的路由跳转之前 都被全局前置守卫处理
- router.beforeEach((to,from,next)=>{
to 表示目标路由
from 表示现在路由
next 表示是否继续
next('path') 直接跳转某一路径
})
- 用处 登录状态的检测
全局后置守卫
router.afterEach((to,from)=>{
console.log('全局后置')
console.log('from',from)
console.log('to',to)
})
局部守卫
- 在组件的路径里书写 只对你写的这个组件有用
-
{
path:'/my',
component:My,
beforeEnter(to,from,next){console.log('路由独享守卫 局部路由守卫') next()
}
}- 只针对与某一个路由 当某一个组件(个别组件需要登录检测)需要使用时 可以使用局部路由守卫
全局解析守卫
- 使用场景和使用方式与全局前置类似 区别于在执行的时机不一样
- 区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
组件内的守卫
- beforRouteUpdate
- 组件内的守卫更新之前 动态路由 参数发生修改 组件时复用的不会重新创建销毁
- created 生命周期只有在创建的时候执行一次 vue12.pm
- beforeRouteEnter 内部没有this
- beforeRouteUpdate 动态路由的组件动态路由改变的时候不用重新创建而是复用 获取参数
- beforeRouteLeave 组件离开的时候执行 复用组件 之前的切换 不算离开
插槽
- 插槽 slot
- 通常我们在组件的标签里写东西时显示不出来的 要使它显示出来 就需要在你想要显示的地方引入slot slot里的内容就相当于你想要显示的内容
- 具名插槽
- 给每一个插槽取一个名字
<p slot="top">在上面</p>
使用的话: <slot name="top"></slot>
vue动画
- 1.在官网下载animate.css
2.在需要用动画的组件引入 @import '../base/animate.css';
3.在需要做动画的地方加上一个<transition></transition>
4.在transition 上添加 动画 enter-active-class="zoomIn animated"
leave-active-class="rotateOut animated"
- animated 必须要 动画效果可以自己选择
Vuex
-
提供全局状态管理的模块
多组件共享状态
1.又多个组件用了同一变量
2.变量发生改变后组件要发生变化例子:音乐播放器里的播放器 所有的歌曲都会触发这个组件 并且每首歌播放 里面的数据就是当前这首歌的全部数据
state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。
有一个store文件 在main.js 里面进行注册
使用方式
-
1.创建配置
- 引入vue
引入vuex
使用Vuex
创建Vuex的store对象
抛出
- 引入vue
2.注册store
参考路由在main.js 的实例中注册store 就会有$store 对象3.使用全局状态值
this.$store.state.数据的key值4.修改全局状态值
vuex 中规定 修改全局状态值必须通过mutations 里的方法
this.$store.commit('mutations里的函数名',传递的参数)-
5.其他优化
actions 存放异步操作 1.减少异步代码的重复 2.统一管理异步请求 3.时间旅行
对象
组件里通过 $store disptach 触发action 里的方法
action里执行异步 执行完毕再通过commit 触发mutation- getters 当成vuex 里的计算属性
是一个对象
创建一个新的变量 该变量和state值相互关联
- getters 当成vuex 里的计算属性
-
辅助函数
值 state getters
将值映射到计算属性
mapState mapGetters函数 mutations actions
将函数映射到methods
-
核心概念
- Mutation Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
- mutations: {
increment (state) {
// 变更状态
state.count++
}
}
-
在你需要使用的组件的methods里
- this.$store.commit('mutations里的函数名',传递的参数) 使用这个方法
- 第二个传递的参数可以用来修改值
-
State 用来存储你想要改变的全局变量 想要改变的变量都要放到state里面
- 例如:let store=new Vuex.Store({
//全局状态 全局变量
state:{
toggle:false
},
})
- 例如:let store=new Vuex.Store({
actions 处理异步请求 例如 ajax请求数据
作用:1.减少异步代码的重复 2. 统一管理异步 3.时间旅行
-
在actions里面写方法
-
actions:{
changeNameNet(context,params){
let {commit}=context
//模拟异步操作setTimeout(()=>{
commit('changeName',params)},1000)
}
}
-
在使用这个方法的组件里 methods来
组件里通过 $store disptach 触发action 里的方法
action里执行异步 执行完毕再通过commit 触发mutation(其实也是同步,还是要经过mutation 来实现)this.$store.dispatch('changeName',{name:'aaaa'})
getters 计算属性相当于
- 创建一个新的变量 该变量和state值相互关联
- getters:{
testNum(state){
return ((state.num*2)+5)
}
}
使用方法 {{this.$store.getters.testNum}}
辅助函数
-
值 state getters
将值映射到计算属性
mapState mapGetters函数 mutations actions
将函数映射到methods -
例子:{{tis.$store.state.name}}
- 在之前使用 import {mapState} from 'vuex' ,然后直接在要使用的组件里的computed里写 ...mapState('name','num')
- 在组件模板里直接使用 '{{name}}' 相当于 {{this.$store.state.name}}
getters和state一样
-
mutations
- 在之前使用 import {mapMutations} from 'vuex' ,然后直接在要使用的组件里的methods里写 ...mapMutations(['changeName','changeToggle'])
- 在组件模板里methods里的使用 this.changeName({name:'aaa'}) 就相当于 this.$store.commit('changeName',name:'aaa')
想要避免出现重名的时候 就把...mapMutations里不用传数组 改为对象的形式 key值为你的新改的名字
actions 异步方法一样的用法
module 模块化
要想使用模块化 就要在store文件下创建模块 Amodule,Bmodule 创建一个index.js 封装state,mutation,actions,getters,在index里面导入Amodule使用import
-
let store=new Vue.Store({
module:{
'A':Amodule,}
}) 为了防止重名 在每个模块里面加上 namespace:true;
项目 移动端的兼容问题
移动端适配 : rem+flex+vw vh
rem 1rem=根元素字体大小的字高 根据html的footsize
em 1em = 1字高 body中的 font-size
pxpc端适配 : 百分比+媒体查询
大于最大尺寸 内容不变 留白变大
最大尺寸
内容层百分比布局
最小尺寸
内容不变 产生滚动条
480 -750 -1136 -1440 -1920 -2440-
响应式(移动pc适配) 媒体查询 栅格 bootstrap 官网首页
响应式布局 媒体查询 栅格 bootstrap
-
第一步 在public里面的index.html 设置
- document.documentElement.style.fontSize=document.documentElement.clientWidth/10+'px'
console.log( document.documentElement.style.fontSize)
- document.documentElement.style.fontSize=document.documentElement.clientWidth/10+'px'
第二步 在style文件夹里面 mixin.less 写下面的东西 选取设备分辨率 谷歌浏览器的最小为12px 例如 375
在variable 里面设置根元素的分辨率大小 以后想要改的话 直接修改@remSize 的值 //设置根元素的分辨率大小
@remSize:37.5px;.w(@px){
width: unit(@px/@remSize,rem);
// @px=375
// width: 100rem;
// unit(数量,单位) 给数量添加单位
}
.h(@px){
height: unit(@px/@remSize,rem);
}
.t_c(){
text-align: center;
}
.l_h(@px){
line-height: unit(@px/@remSize,rem);
}
// 固定布局
.fixed(@top,@bottom,@left,@right,@color){
position: fixed;
top: unit(@top/@remSize,rem);
bottom: unit(@bottom/@remSize,rem);
left: unit(@left/@remSize,rem);
right:unit(@right/@remSize,rem);
background:@color ;
}
项目开发
- 使用public文件下的图片直接写根路径
- <img src="/favicon.ico" alt="">
- public
使用根路径 字符串变量都行
其他文件夹 使用相对路径 字符串ok 变量必须通过import 引入图片
- 1.import img from "../assets/logo.png"
- 2.data(){
return{
// img1:"/favicon.ico",
// img2: img //"../assets/logo.png"
}
}
- 3. <img :src="img1" alt="">
<img :src='img2'>
网络请求
+ 第三方插件 axios
- 在created 里发起ajax请求
-
Es6 抛出方式
+ export const login=()=>{
//具名抛出 一个文件可以使用多个具名抛出
}
export default 一个文件只能又一个