首先 介绍几个常见指令 指令:以属性的形式出现在标签上 v-xxx
1、内置指令 数据绑定指令 v-html v-text 举例 <span v-html="msg">将msg这个数据对应内容展示在这里<span>
2、条件指令 v-if v-else v-else-if v-show 前者控制DOM结构是否加载 一般用于页面刚初始化进来 后者控制DOM结构显示隐藏
3、循坏指令 v-for 可以循坏的有 array object string number 注意v-for在vue2.0版本要搭配key使用 v-for的优先级也要比v-if的优先级高
4、属性绑定指令 v-bind:属性名 可以简写为 :属性名
这里注意下class和style的用法 拿class举例 :class=["active"] :class={"active":条件为真添加} 前者是数组模式 给所有的元素添加类 后者是符合条件的元素添加类 style类似
5、事件绑定指令 v-on:事件名 可以简写@事件名
6、v-pre 绑定这条指令元素不会编译{{}} 这个语法 原样输出
7、v-once 只绑定一次数据 第二次当做静态页面渲染 数据改变此元素不会改变
8、v-cloak 在页面初始渲染的可能会因为页面的网速问题将{{}} 这些东西展示到页面上 给元素添加这个指令并且配合css样式[v-clock]:{display:none}可以避免
注:利用nextwork右上角的Offiline设置Slow:3G 可以模拟网速问题
<hr>
上述介绍介绍了几个常见指令 下面介绍下组件内如何定义自定义全局指令
1 Vue.directive(指令名字,{ 2 //在我们自定义指令的函数中每个函数的第一个参数 3 //永远是el 表示被绑定了指令的那个元素 4 //这个el元素是一个原生的js对象 也就是一个普通的DOM 5 //它具有普通DOM能够操作的所有方法 6 第二个参数是binding 这是一个对象 包含以下属性 7 name:指令名,不包括 v- 前缀。 8 value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。 9 oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated钩子中可用。无论值是否改变都可用。 10 expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。 11 arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。 12 modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar中,修饰符对象为 { foo: true, bar: true } 13 14 15 bind:function(el){ 16 每当指令绑定到元素上的时候,会立即执行bind这个函数 17 只会执行一次这个函数 18 }, 19 inserted:function(el){ 20 inserted表示元素插入到DOM中的时候,会执行inserted这个函数 21 }, 22 updated(el){ 23 //当组件或者vNode更新的时候会执行 可能触发多次 24 } 25 })
局部定义指令如下
1 //局部自定义一个v-color指令 2 directives:{ 3 color:{ 名字 里面是钩子函数 4 bind(el,binding){ 5 console.log(binding) 6 el.style.color="red" 7 } 8 } 9 }
注:更加详细的可去官网查看
<hr>
此时指令基本告一段落了 接下来介绍几个修饰符
.number 必须输入数字
.lazy 把input事件改成change事件
@keydown.enten 表示只有按enter键才会触发 也可以直接.13
@keydown.enten.shift 表示同时按下shift和enter才会触发
.delete 删除键或者退格键
//将f2这个键的键盘码定义成113 前面是名称 后面是真正的键盘码
.stop 阻止冒泡
.self 只在自身触发 给父元素添加 点击子元素不会冒泡触发了
父元素的事件
.once 只触发一次
此时修饰符基本结束在介绍下计算属性与watch还有this.$nextTick
语法是 this.$nextTick(function(){}) 或者是this.$nextTick().then(res=>{
})
vue中的生命周期 重点
总体来说分为三个阶段 创建阶段 更新阶段 销毁阶段
1、创建阶段 只会执行一次 可分以下几个钩子函数
1、beforeCreate 收集配置,初始化事件
6、updated 数据生成后新的DOM生成后就触发了
7、beforeDestroy(){} //销毁前
8、destroyed(){}//销毁后
9、activated
keep-alive 组件激活时调用。
该钩子在服务器端渲染期间不被调用。
10、deactivated
类型:Function
详细:
keep-alive 组件停用时调用。
该钩子在服务器端渲染期间不被调用
组件
一般我们重复使用的排版封装成一个组件
在使用是组件的时候我们需要先利用 import 名字 from 组件路径 将一个组件引入 然后在components里面注册一下
接着我们就可以在我们想使用的地方用标签的样式直接调用这个组件了
组件还分为内置组件和动态组件
内置组件
template component keep-alive 缓存组件的
//排除shop这个组件 也就是不缓存这个
<keep-alive include="shop"></keep-alive>
//只缓存shop这个组件 其他的不缓存
//缓存多个就是直接加逗号接着写就行
<keep-alive :include="shop/"></keep-alive>
这种写法就是正则匹配写法
<component :is=""></component>
is里面是什么就显示哪个组件
slot 插槽 内容分发 一般用在父组件给子组件传递
复杂的html标签或者内容时使用
在子组件里面去定义
如果父组件没有配置内容 直接使用默认内容
1个组件可以slot插槽
插槽可以起名字(具名插槽)
父组件分配内容,使用父组件的内容
slot默认的name名字叫做default
vue中三种传参问题
先在main.js中
Vue.prototype.$bus=new Vue();
然后在修改数据的组件中的created 这个生命周期中 一般就是根组件
this.$bus.$on(事件名,(参数一)=>{
//回调函数接受参数一
})
准备想修改的组件中
this.$bus.$emit(事件名,参数)
注意公交车在两个毫无关联的页面发车可以是在这个页面的销毁前的生命周期中
发车 然后在另一个页面的created生命周期中接车 缺点就是这样接受到的数据
一刷新就会丢失
父向子传参
动态的:名字='参数';
子组件接收 动态的props
子向父传参
在子级
this.$emit(事件名,参数一,参数二)
在父级接受用哪个标签 @事件名=函数名 在methods里面调用
子向父传参还有一个终极版的方法
我们可以把父组件的函数通过props的形式然后传给子组件
接着通过在子组件调用父组件的函数进行传参来改变父组件的变量
总之通过props可以完成基本所有的传参问题 包括公交车传参
也可以一级一级的去完成 基本原理就是子组件调用父组件的函数
然后在父组件自己执行函数
路由
pathVue Router 是vue.js的官方的路由管理器
spa :single page application 单页面应用开发
原理:onhashchange 事件
window.onhashchange()=>{
console.log(location.hash)
//当页面的hash发生改变后就会触发
}
单页面开发的优点
提供流畅的用户体验 不用重新请求页面服务器压力小
缺点:不利于seo搜索 首次加载慢 历史管理需要自己编程管理
使用路由步骤
1、定义组件对象
2、创建路由的实例
3、配置路由规则
4、在Vue的实例配置路由功能
下面介绍几种路由的跳转和获取
声明式跳转
<!-- <router-link tag="li" to="/detail/0">新闻一</router-link>
<router-link tag="li" to="/detail/1">新闻二</router-link>
<router-link :to="{path:'/main/home'}">首页</router-link>
<router-link :to="{name:'menu'}">订单</router-link>
-->
<!-- <li @click="goDetail">新闻一</li>
<li @click="$router.push('/detail/1')">新闻二</li> -->
{
path:"/hoem/:id', 配置
name:home,
component:home
}
获取
当前的路由对象
$route
用法 {{$route.params.id}}
//或者this.$route.params.id
还有一个全局的路由对象
$router
this.$router.go(-1)//回到上一个路由
this.$router.replace();//替换
替换的参数和push一样
编程式跳转
#### 编程式跳转
this.$router.push('/detail') // 字符串
this.$router.push(`/detail/${bianliang}`)
动态路由发送 接收this.$route.params.xxx
index配置 path:/detail/:id
this.$router.push({path:'/detail/0'}) //对象
this.$router.push({name:'detail',params:{id:0}}) //对象
//注意这种是利用规则里面配置的name path不能结和params
在获取时,this.$route.params.xxx
params传参一刷新就没了
query传参会拼接在URL地址后面 刷新也不会消失
this.$router.push({path:'/detail?id=0'})
this.$router.push({name:'detail',query:{id:0}})
this.$router.push({path:'/detail',query:{id:0}})
在获取时,this.$route.query.id
//利用axios传参第二个参数传参与后台的接受
//注意第二个参数写{params:{}} 在里面的对象里写我们需要的数据
this.$http.get('/api/detail',{params:{id:this.$route.params.id}}).then(res=>{
console.log(res.data,"详情页接收到的数据")
})
后台接收是console.log(req.query)
配置路由的时候二级菜单可以不写全 他会自动补全 但是注意不能加/
例如下面例子
也就是children里面的path配置 那个hit前面不能加斜杠 不然不会自动补全前面的
但是重定向需要写全了 只有在children里面的才不用写全
再放一波简易版的路由配置
1 routes: [ 2 linkActiveClass:“active”, //点击时候自动给添加class类名 3 { 4 path: '/home', 5 name: 'home', 6 component: home, 7 redirect:"/home/hit", 8 children:[ 9 { 10 path:'hit', 11 component:IsHit 12 },{ 13 path:'upcomingMovies', 14 component:upcomingMovies 15 } 16 ] 17 },{ 18 path: '/login', 19 name: 'login', 20 component: login 21 },{ 22 path: '*', 23 redirect:"/home" 24 } 25 ]
路由拦截
组件内守卫
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
有三个参数 to from next
next可以穿path 或者什么都不传 布尔值
全局的钩子函数 上面三个是在某一个组件内
beforeEach 路由跳转之前
afterEach 跳转之后
注意这个函数是指的进入了这个页面后触发的所以没有next参数
用法 在index.js中
let router=new Router({})
router.beforeEach((to,from,next)=>{
写完逻辑调用next
})
hash和history传参问题
hash只在前端使用
history 并不真实存在
切换路由模式
在router下面的index.js中
new Router({
mode:"history" 这样就是history模式 不加#号
mode:"hash" 默认是这个 #后面的
})
过滤器
注意过滤器没有修改原数据 而且不需要数据改变后触发 这和computed有区别
vue.js允许你自定义过滤器 可被用作一些常见的文本格式化
过滤器可以用在两个地方 mustache差值和v-bind表达式
过滤器应该被添加在JavaScript表达式的尾部 由管道符指示 管道符:“|”
举例 {{name|过滤器名称(传参)}} 这样写的话页面就不会直接把name输出 而后先
执行name后面的过滤器 然后在输出name
还可以多次调用过滤器 例如 {{name|过滤器1|过滤器2}}
从左往右执行 别最后一个过滤器输出的东西赋值给name
全局定义
定义一个过滤器 Vue.filter("过滤器的名称",(参数一,参数二)=>{
参数一被定义死了 永远是过滤器管道符前面哪一个数据
参数二是过滤器传过来的参数
函数里面写要对传过来的数据进行什么处理
})
私有过滤器
filters:{
过滤器名称和处理函数 写法类似于methods :{}
}
过滤器调用就近原则 意思就是私有过滤器和全局过滤器名字重复 先执行私有
案例说明
改变msg的值然后展示在页面上面去
<template>
<div>
<h4>订单</h4>
{{msg|serch}}
</div>
</template>
<script>
export default {
data(){
return {
msg:"我想实现过滤器"
}
},
filters:{
serch(el){
console.log(el)
return el.replace("想实现","成功实现了")
}
}
}
</script>
vuex
主要解决两个没有关联页面的通讯问题
接受仓库的数据
this.$store.state
//触发仓库中的mutation
this.$store.commit("事件名",type)
第一个参数是仓库中定义的函数名 第二个参数是想传的参数
仓库store下面js的写法是
import Vue from 'vue';
//先引入Vue
import Vuex from 'vuex';
//在引入Vuex
Vue.use(Vuex);
//将Vuex挂载到Vue上面去
//引入中间件 记录操作日志的作用
import Logger from 'vuex/dist/logger'
//引入子模块
import index from './modules/index'
//生成一个vuex实例
export default new Vuex.Store({
modules:{
index
},
plugins:[Logger()]
});
其中某一个子模块的简单的写法
//index模块的数据
const state = {
count: 100
}
//同步数据的改变 在模块中修改数据就是触发的这个事件
const mutations = {
//state表示当前模块的状态 payload表示触发当前mutations携带的数据
changeCount(state, payload) {
payload == "+" ? state.count++ : state.count--
}
}
export default {
namespaced:true, 在抛出的时候加上这个就可以指定组件通讯
下回访问的时候就要这样访问了
this.$store.commit("模块名/事件名",type)
state,
mutations
}
最后一步在main.js引入这个仓库store下面的js并放在vue实例上
其实vuex就是两种数据
一种同步
const mutations={
//这里写一些同步的函数操作
}
然后使用 this.$store.commit("left/change",id)
这个东西去触发同步的使用
第二种是异步
const actions={
//这里写一些异步的函数请求
//假如说在这些异步请求中需要改变state里面的数据
//需要结构出这个函数的第一个参数里面的{commit}
//来触发同步让其state进行改变
//具体看下面例子
}
const actions = {
getleft(context, payload) {
//为了获取完左边的时候默认获取右边第一条数据 我们需要给这个函数
//整上一个promise对象 让其有返回值来让我们知道这个请求已经完成了
return new Promise((resolve, reject) => {
let {
commit
} = context;
//console.log(commit)
getLeft().then(res => {
//提交局部的mutations
commit("updateLeftData", res.leftData);
//提交全局的mutations
commit("right/updateRightData", res.rightData, {
root: true
})
resolve()
//console.log(res.leftData, "左边数据的网络请求")
})
})
}
}
用来触发异步的actions可以使用
//触发一下网络请求
this.$store.dispatch("left/getleft").then(res => {
//在左边数据完成以后默认触发右边第一个数据
//再去触发右边仓库
this.$store.commit("right/rightchange", 1);
});
另外我们可以使用辅助方法来触发仓库
import {mapState,mapActions,mapMutations,mapGetters} from "vuex"
第一个是获取仓库中的state数据 用法在computed下面
...mapState({
buyList:state=>state.shop.buyList
}),
key值直接使用 后面是state.模块名.数据名
第二个是触发仓库的异步请求方法 用法是在methods下面
methods: {
...mapMutations({
changeNum:"shopange"
})
},
直接调用前面名字就可以了 后面是模块名+触发的函数名
第三个是触发同步方法
用法和上面一样
methods: {
...mapMutations({
updatebuyList:"shop/updatebuyList"
}),
}
第四个是仓库里面的一个计算属性类似于computed
animate.css
使用animate.css这个第三方库实现动画效果
<transition
enter-active-class="第三方的一些名字实现进场动画"
leave-active-class="第三方的一些名字实现出场动画"
:duration="800" 入场和离场的时间 统一设置
:duration={leave:133,enter:433} //分开设置
>
包裹想要有动画效果的元素
<元素 class="animated">
</transition>