Vue2
补充1:vue中对象修改
1.新增属性
this.$set(this.obj,"sex","女")
Vue.set(this.obj,"sex","女")
2.删除属性
this.$delete(this.obj,"sex")
Vue.delete(this.obj,"sex")
3.修改数组
this.$set(this.obj,sex,0,"女")
this.obj.sex.splice(0,1,"女")
vue-router
路由基本使用
main.js
import VueRouter from 'vue-router'
Vue.use(VueRouter)
new Vue({
router,
})
App.vue
import VueRouter from './router'
export default {
components: { },
VueRouter,
// 路由跳转进入该组件时调用
beforeRouteEnter (to, from, next) {
next()//继续跳转
},
// 路由跳转离开该组件时调用
beforeRouteLeave (to, from, next) {
}
}
router/index.js
import Vue from 'vue'
import Router from 'vue-router'
import home from '@/components/home' //引入跳转所需的组件
import about from '@/components/about' //引入跳转所需的组件
Vue.use(Router)
const router = new Router({
mode: 'history',//hash模式有#且性能好;history相反
routes: [
{
path: '/about/:id/:title',
name: 'about',
component: about,
meta: {isAuth: true, title: 'about'} // 是否需要鉴权
// props($route){
// return {id:$route.params.id,title:$route.params.title}
// },
// children: [
// {
// path: 'aboutson',
// component: message
// }
// ]
},
{
path: '/home',
name: 'home',
component: home,
props ($route) { // 解构赋值{ query }:直接query.id、query.title/{query:{id,title}}:直接id、title
return {id: $route.query.id, title: 'hello'} // params
}
// 独享路由守卫
// beforeEach: (to, from, next) => {
// }
}
]
})
// 前置路由守卫
// router.beforeEach((to,from,next) =>{
// if(to.meta.isAuth){//需要鉴权
// if(localStorage.getItem('token') === 'wjj'){
// next();
// }else{
// alert('权限不足!!!');
// }else{
// next()
// }
// }
// })
// 后置路由守卫,
// 应用:路由切换后切换窗口的图标,document.title(to.meta.title)
// router.afterEach((to,from) =>{
// if(to.meta.isAuth){//需要鉴权
// if(localStorage.getItem('token') === 'wjj'){
// next();
// }else{
// alert('权限不足!!!');
// }
// }
// })
export default router
跳转的按键:home
展示的组件:
携带参数
params参数(对象写法)
//router.js文件中的routes对象
{
path: '/home/:id/:title',
name: 'home',
component: home,
}
//页面的路由to
:to='/home/1/你好'
2.对象形式,只能用name
:to="{name:"home",params:{id:1}}"//必须用name
query参数:$route.query.id
:to="/home?id=001$title=你好
2.对象形式
:to="{path:"/home",query:{id:1,title:"你好"}}"
props配置
- 对象形式,该对象中的所有key-value都会以props的形式传给组件,组件接收:props:['id','title']
- 值为布尔值,props:true,为真时,将该路由收到的params参数以props的形式传给home组件
- 函数,props(){return {id:1,title:"你好"}}
replace属性
给router-link标签添加replace属性,history(历史路径)中会直接被替换
编程式导航
给DOM元素添加触发事件,调用方法接收数据实现跳转和传参@click="handleClick(item)"
this.$router.push({name:"home",query:{id:1}})
this.$router.replace({name:"home",query:{id:1}})
this.router.back()
缓存路由
包裹的保持挂载,不被销毁
<keep-alive include="Home”></keep-alive>//include属性包含的是不被销毁的组件
路由守卫
router/index.js中有代码样例
绑定class样式
1.字符串写法:
:class="className"//class为data中的数据,用于存放此时生效的类名
2.对象写法:(常用)
:class="{样式一:true,样式二:false}"
3.数组写法:
:class="['class1','class2']"
js数组方法
1.join()
就是把数组转换成字符串,然后给他规定个连接字符,默认的是逗号( ,),书写格式:join(" "),括号里面写字符串 ("要加引号"),
2.push()和pop()
push(): 把里面的内容添加到数组末尾,并返回修改后的长度。
pop():移除数组最后一项,返回移除的那个值,减少数组的length。
3.shift()和unshift()
shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
unshift():将参数添加到原数组开头,并返回数组的长度 。
4.sort()
将数组里的项从小到大排序
arr.sort((a,b) => a-b)
5.reverse()
反转数组项的顺序,在原数组的基础上进行改变。
6.concat()
将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。书写格式:arr.concat(),括号里面写内容 ("字符串要加引号")
7.slice()
截取数组,可以接收1-2个参数,如果只有一个参数,返回从该参数指定位置开始到当前数组末尾的所有项;如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
8.splice()
删除、插入和替换。
删除:指定 2 个参数:要删除的第一项的位置和要删除的项数。
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数为0所以是插入)和要插入的项。
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要替换的原数组的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。
9.indexOf()和lastIndexOf()
indexOf() 接收两个参数:查找的项、开始查找的位置;接收一个参数:只接收查找的项,默认从头查找
lastIndexOf() 接收两个参数:查找的项、开始查找的位置。其中, 从数组的末尾开始向前查找;接收一个参数:只接收查找的项,默认从尾部查找
10.forEach()
对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值直接修改原数组。
arr.forEach(( item, index, self) => {
//item:每一项,index:索引,self:arr数组
})
11.map()
对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法返回一个新数组,不修改原数组。
arr.map(item => {
return item+1;
})
12.filter()
“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。这个方法返回一个新数组,不修改原数组。
arr.filter(( item, index, self) => {
return item >= 5;
})
or
arr.filter(( item, index, self) => return item >= 5)
13.every()
判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
arr = [1,2,3,4,5]
var arr2 = arr.every(function(x) {
return x < 3;
}); //arr2 false
14.some()
判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
arr = [1,2,3,4,5]
var arr2 = arr.some(item => {
return item < 3;
})//arr2 true
vue监测数据改变的原理
vue的双向绑定
核心是Object.defineProperty()方法,Object.defineProperty(obj, prop, descriptor),其中:obj为要在其上定义属性的对象,prop是要定义或修改的属性的名称,descriptor是将被定义或修改的属性描述符。
通过defineProperty()实现绑定,每当数据变化时都会调用set()方法,可以根据此来实现一个双向绑定。
DocuemntFragment(碎片化文档)
你可以把它认为是一个dom节点的容器,当你创造了10个节点,当每个节点都插入到文档当中都会引发一次浏览器的回流,也就是说浏览器要回流10次,十分消耗资源。 而使用碎片化文档,也就是说我把10个节点都先放入到一个容器当中,最后我再把容器直接插入到文档就可以了!浏览器只回流了1次。 注意:还有一个很重要的特性是,如果使用appendChid方法将原dom树中的节点添加到DocumentFragment中时,会删除原来的节点。
nodeToFragment将节点劫持
组件
组件局部引用
1.export defaul
2.import 组件名 from ‘路径‘
3.components:{组件名}
组件全局引用
1.index.js
import homelist from './homelist.vue'
export default {
install: function (Vue) {
Vue.component('homelist',homelist);
}
}
2.main.js
import homelist from './components/homelist/index.js'
Vue.use(homelist);
3.直接使用
vue项目文件结构
babel.config.js ES6转换为ES5
package.json 包说明书,说明项目中使用的依赖
### this.$refs
给标签添加ref属性,如:
可以通过this.$refs.form获取到这个元素,相当于原生js中的did
props传值
用于父组件向子组件传值
子组件:child.vue
props:{
name:String,//name:{type:String,default:'lihua',required:true,}
}
父组件:parent.vue
<child :name='xiaoming'></child>
mixin混入
mixin.js文件
expfort const mixin = { //mixin一般为混入的文件名
data() {
return {
}
},
methods:{
},
}
.vue组件文件
import { mixin } from '路径'
mixins:[ mixin,]
directive插件
src/plugins.js
export default {
install(Vue){
//全局过滤器
Vue.filter('mySlice',{value => value.slice(0,4)})
//自定义指令
Vue.directive('fbind',{
//类似于生命周期:指令与元素成功绑定时
bind(element,binding){
element.value = binding.value
},
//类似于生命周期:指令所在的元素插入到界面中时
inserted(element,binding){
element.focus()
},
//类似于生命周期:指令所在的模板数据更新,被重新解析时
updata(element,binding){
element.value = binding.value
},
})
Vue.mixin({
data(){
return {
x: 100,
y: 200,
}
},
})
Vue.prototype.demo = () => {
alert("警告!")
}
}
}
main.js
import plugins form './plugins'
Vue.use(plugins)
本地缓存
1.localStorage
//在localStorage中添加值
localStorage.setItem("name","xiaoming");
//存储一个对象:localStorage.setItem("name",JSON.stringify(obj));
//在localStorage中获取值
localStorage.getItem("name");
//获取一个对象:JSON.parse(localStorage.setItem("name"));
//在localStorage中获取值
localStorage.removeItem("name");
//清空localStorage
localStorage.clear();
特点:关闭浏览器后存储的东西也不会消失
2.sessionStorage
api与localStorage的相同
特点:存储的东西随浏览器窗口关闭而清除
父子组件传值
父传子
props
子传父
-
子组件:this.$emit("ok",this.data);父组件:@ok="handleOk" handleOk(data){}
-
this.on("ok",function回调方法)
this.once("ok",function回调方法)
解绑自定义事件
<button @click="offBind"></button>
offBind(){
this.$off("ok")
}
//解绑多个事件,this.$off(["ok1","ok2"])
//解绑所有事件,this.$off()
全局事件总线
作用:任意组件之间的通信
main.js
beforeCreate(){
Vue.prototype.$bus = this//安装全局事件总线
}
发送方组件
this.$bus.$emit("hello",666)
接收方组件
mounted(){
this.$bus.$on("hello",(data) =>{
console.log("接收到的数据为",data)
})
},
beforeDestroy(){
this.$bus.$off("hello")
},
消息订阅与发布
推荐第三方库:pubsub-js
安装:npm i pubsub-js
引入:import pubsub from 'pubsub-js'
订阅消息:
mounted(){
this.pubId = pubsub.subscribe('hello',( msgName, data) => {//msgName:消息名,data:传递的数据
console.log("组件发布了消息,hello消息的回调已经执行,收到消息:",data);
})
},
beforeDestroy(){
pubsub.unsubscribe(this.pubId)
},
发布消息:
pubsub.publish('hello',666)
this.$nextTick()
作用:规定一个回调函数,在解析模板dom节点更新后执行回调函数
### vue封装的动画效果
.come {
animation:show 1s;
}
.go {
animation:show 1s reverse;
}
@keyframes show{
from {
tranform:translate(-100%);
}
to {
tranform:translate(0px);
}
}
<template>
<div>
<button @click="changeAction">{{action}}</button>
<transition name="hello" :appear="true">
<h1 class="title" v-show="isShow">显示/隐藏</h1>
</transition>
</div>
</template>
<script>
export default {
data() {
return {
action: "显示",
isShow: false,
}
},
methods:{
changeAction(){
if(this.action == "显示") this.action = "隐藏";
else this.action = "显示"
this.isShow = !this.isShow
},
}
}
</script>
<style>
.hello-enter-active {
animation: show 1s linear;
}
.hello-leave-active {
animation: show 1s reverse;
}
.title {
width: 300px;
height: 60px;
background-color: blue;
}
@keyframes show {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
</style>
重点:
- 包裹标签
- 定义css样式,.v-enter-active和.v-leave-active,在里面写animation的动画效果
- 给transition标签加上name属性,类名变为name-enter-active和name-leave-active
- transition标签加上appear属性可以自动放映动画
过度效果
.v-enter,.v-leave-to {//进入\离开的起点
transform: translateX(-100%);
}
.v-enter-active,.v-leave-active {//进入、离开的过程
transition: 0.2s linear;
}
.v-enter-to,.v-leave {//进入、离开的终点
transform: translateX(0);
}
多个元素过度
其中的所有元素都必须有一个key值
引入第三方样式animate.css
<transition-group
name="animate__animated animate__bounce"
enter-active-class="animate__swing"
leave-active-class="animate__backOutUp"
appear
>
<h1 class="title" v-show="isShow" key="1">显示/隐藏</h1>
<h1 class="title" v-show="!isShow" key="2">显示/隐藏</h1>
</transition-group>
ajax跨域
项目根目录vue.config.js文件
pathRewrite: ('^/api',''),//重写请求的路径向服务器发送正确的请求路径
ws: true,//用于支持websocket
changeOrigin: false,//前端8080向后端5000发起请求,该属性为fasle时代理服务器被服务器认为是8080端口,反之则为5000
vue-resource
简介:vue1.0早期使用较多的插件库,官方目前已不再维护,交给其他团队维护。
插槽
在可复用组件中需要改变的地方加入标签,在使用组件时在组件标签中使用
标签中可以嵌套一些默认的标签,当使用者没有使用slot时出现
具名插槽
<slot name="demo">默认出现的文字</slot> //student组件
<student> //父组件使用组件student
<input slot="demo"/>
</student>
目前插槽已经被弃用,变为v-slot:name=”message“,简写为#name,只能在template中使用
作用域插槽
父组件
<slot-demo :userObj="userObj">
<template v-slot:footer="message"> // v-slot可以简写为#,footer是子组件中slot的name
<div>{{message.userAge}}</div>
<div>{{message.userName}}</div>
//这里用的message是写组件时在slot标签上定义属性的映射。
</template>
</slot-demo>
子组件
// 这里的userObj是子组件数据,通过作用域插槽传给父组件使用
// 此处传给父组件的数据为{userAge: userObj.age, userName: userObj.name}
// 即为父组件中v-slot:footer="message"处的message
<slot name='footer' :userAge="userObj.age" :userName="userObj.name" ></slot>
### Vuex
原理图:
npm i vuex
引入 Vuex import vuex from 'vuex'
应用 Vue.use(Vuex)
new store
步骤:
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const actions = {
add(context,value){//{commit}
context.commit('add',value)
},
}
const mutations =
add(state,value){
state.sum += value
},
}
const state = {
sum: 0,
}
const getters = {
tenSum({sum}){
return sum*10
}
}
export default store = new Vuex.Store({
actions,
mutations,
state,
getters,
})
main.js
import store from './store'
new Vue({
store,
})
组件.vue
this.$store.dispatch("add",2) //2是value
this.$store.getters.tenSum
mapState、mapGetters写到组件computed里面
mapActions、mapMutations写到组件methods里面
- 对象写法:
...mapState({sum:"sum"})
- 数组写法
...mapState(['sum'])
- 自己写
dataName(){return this.$router.state.sum}
namespace
const a = {
namespaced:true,
actions:{},
mutations:{},
state:{sum:0},
getters:{},
}
...mapState('a',['sum'])
另一种写法:(原生手写)
this.$store.state.a.sum
this.$store.getters['a/tenSum']
this.$store.commit('a/add',n)
this.$store.dispatch('a/addWait',n)
module
项目中写法:
src/store/modules/路径下多个.js文件,每个都类似:
import Vue from 'vue'
const a = {
namespaced:true,
actions:{},
mutations:{},
state:{sum:0},
getters:{},
}
export default a
//或者export default {}
src/store/路径下的index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
import app from './modules/app'
import user from './modules/user'
import getters from './getters'
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
app,
user,
},
getters,
})
最后main.js import store from './store' 导入store/index.js文件中的所有配置
\