vue 基础
常用指令:
v-model 数据双向绑定
v-bind 修改属性值 :
v-on 事件绑定 @
v-text 渲染纯文本
v-html 渲染超文本
v-show 控制显示隐藏 display
v-if 控制显示隐藏 移除元素
v-for 列表循环
v-bind:key 独立索引值
MVVM 模型
M 模型 ========》VM vue 对象 《=========V 视图
数据代理:利用 Object.defineProperty
实现 方便操作 data 数据
事件修饰符
prevent: 阻止默认事件
stop: 阻止事件冒泡
once:事件触发一次
获取元素
可以用来操作Dom
标签内设置名称
ref='title'
获取
this.$refs.title
✨传值操作
props
让组件接受外部传进来的数据
父传子
写在子组件,并对接受类型限制
props: {
name: String,
age: Number,
},
完整写法
props: {
name: {
tpye: String,
required: true, //是否为必须
},
age: {
type: Number,
default: 99, //默认
},
:age='18'
利用动态绑定v-bind传值可参与计算
子传父
在父中定义一个函数,在子中去调用父的函数
父亲
receive(x) {
console.log('@@@app',x);
},
儿子
props: ["receive"],
methods: {
add(e) {
const obj = { id: nanoid(), title:e.target.value, done: false };
this.receive(obj);
},
},
消息订阅与发布
收参数一方订阅消息,发参数一方发送消息
安装第三方库 npm i pubsub-js
引入:import pubsub from "pubsub-js";
订阅消息:
this.pubId = pubsub.subscribe("hello", (msgName, data) => {
console.log(data);
});
发送消息:
sentName() {
pubsub.publish("hello", "@@@");
},
组件自定义事件
通过 v-on:name
绑定自定义事件 通过 this.$emit('name')
调用
解绑:this.$off('name')
解绑多个: this.$off(['name1','name2'])
通过父组件向子组件绑定自定义事件实现 子组件向父组件传值
✨优势:不用在子组件添加props
父组件
<Student v-on:customEvents="demo"></Student>
methods: {
demo(val) {
console.log("触发了自定义事件customEvents", val);
},
}
✨子组件通过this.$emit('name')
调用
子组件
<button @click="sendStudentName">点我触发自定义事件customEvents</button>
methods: {
sendStudentName() {
this.$emit("customEvents",this.name);
},
},
✨全局事件总线(常用)
可以任意组件通信,传值操作
在main.js
里,设置全局事件总线
new Vue({
render: (h) => h(App),
beforeCreate() {
Vue.prototype.$bus = this; ✨
},
}).$mount("#app");
收参数一方:绑定事件总线
mounted() {
this.$bus.$on("hello", (val) => {
console.log("school收到了" + val);
});
},
发送参数一方
sendStudentNameToSchool() {
this.$bus.$emit("hello", this.name);
},
mixin 混入
两个组件共享一个配置
单独写一个js文件,存组件公用的代码块
属性以原本为主,mounted等钩子都实现
引入
import { mixin } from "../mixin";
配置
mixins: [mixin],
使用
<div @click="showName">学生姓名:{{ name }}</div>
plugins 插件
本质为一个含有install的对象,第一个参数为Vue
使用方法
Vue.use(name)
✨给Vue动态添加数据:this.$set('target','key','value')
✨this.$nextTick(()=>{})
下一次DOM更新结束后执行回调
数据改变后进行操作,例如获取焦点
Vue动画
用 <transition name='' appear></transition>
包裹一个标签
appear: 开始时页面有动画
.vue(name)-enter-active {
}
.vue-leave-active {
}
@keyframes identifier {
from {
}
to {
}
}
过渡写法:
.vue-enter{
//进入的起点
}
.vue-enter-to{
//进入的终点
}
.vue-leave{
//离开的起点
}
.vue-leave-to{
//离开的终点
}
.vue-enter-active,.vue-leave-active{
//整个过度的时间
}
第三方动画库:
引入:
import 'animate.css'
使用:
<transition
name="animate__animated animate__bounce"
enter-active-class="animate__backInLeft"
leave-active-class="animate__backOutLeft"
>
<div v-show="isShow">
</div>
</transition>
✨Vue中的ajax请求
引入axios库 npm i axios
解决跨域问题:开启代理服务器
方式一:devServer.proxy
vue.config.js
中
module.exports = {
devServer: {
//目标地址
proxy: "http://localhost:5000",
},
};
请求:public目录中已有的不会转发给5000端口
axios.get("http://localhost:8080/students")
填写目前网页的端口
方式二:
module.exports = {
devServer: {
proxy: {
'/api': { //前缀
target: '<url>', //目标基础路径
pathRewite:{'^/url前缀': ''} //传到后将前缀替换为空字符串
ws: true, //支持websocket
changeOrigin: true //控制请求头的host值
},
'/foo': {
target: '<other_url>'
}
}
}
}
请求:
axios.get("http://localhost:8080/api/students")
vue插槽
默认
<slot>默认值,没有传东西时出现</slot>
具名插槽
<slot name = '123'>
、
使用
<h3 slot = '123'>
<template v-slot:footer>
作用域插槽
数据在组件自身,结构需要使用者决定
将games传给使用者
<slot :games = 'games'></slot>
使用者:
<div>
<tempalte scope = '{games}'> 解构赋值
</tempalte>
</div>
Vue-x
专门在Vue中实现集中式状态数据管理的一个Vue插件
多个组件的共享状态进行集中式的管理(读/写)
适用于任意组件间通信
什么时候使用:
不同组件的我行为需要改变同一状态
多个组件依赖于同意状态(数据)
原理:
1.安装:
npm i vuex@3
vue2使用vuex3版本 ,vue3使用vuex4版本
2.使用:
main.js中
import Vuex from 'vuex'
Vue.use(Vuex)
3.创建store目录下的index文件
//创建vuex中store
//引入Vuex
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
//actions响应组件中的动作
const actions = {};
//mutations操作数据
const mutations = {};
//state存储数据
const state = {};
//创建并且暴露store
export default new Vuex.Store({
actions,
mutations,
state,
});
4.main.js中使用
import store from "./store/index";
new Vue({
render: (h) => h(App),
store,
}).$mount("#app");
在actions
中写业务逻辑
const actions = {
incrementOdd(context, value) {
setTimeout(() => {
context.commit("INCTEMENT", value);
}, 500);
},
};
若actions
中没有操作逻辑,则直接对话commit
this.$store.commit("INCTEMENT", this.n);
组件中读取vuex数据:$store.state.sum
修改vuex中的数据:$store.dispatch('sum',value)
/ $store.cinnut(mutations,value)
vue.getters
加工state中的数据
//加工state中的数据
const getters = {
bigSum() {
return state.sum * 10;
},
};
export default new Vuex.Store({
......
getters,
});
mapState & mapGetter
帮助我怕们映射state
中的数据为计算属性,从state
中读取数据
1.引入
import { mapState } from "vuex";
2.使用
computed: {
...mapState(["school", "subject"]),
// ...mapState({ school: "school", subject: "subject" }),
},
mapMutations & mapActions
生成对应的方法,方法中调用commit去联系mutations
1.引入
import { mapMutations } from "vuex";
2.使用
methods: {
key对应组件中方法,value对应mutations中方法
...mapMutations({ increment: "INCTEMENT", decrement: "DECREMENT" }),
},
传参需要在调用中传递
<button @click="increment(n)">+</button>
Vuex模块化
1.index中配置模块化store
const countOption = {
//开启mapState命名
namespaced: true,
actions: {},
mutations: {},
state: {},
getters: {},
};
2.暴露
export default new Vuex.Store({
modules: {
countAbout: countOption,
personAbout: personOption,
},
});
3.组件中使用
简写:
使用…mapState
methods: {
...mapMutations("countAbout", {
increment: "INCTEMENT",
decrement: "DECREMENT",
}),
...mapActions("countAbout", { incrementOdd: "incrementOdd" }),
},
computed: {
...mapState("countAbout", ["sum", "school", "subject"]),
...mapGetters("countAbout", ["bigSum"]),
// ...mapState({ school: "school", subject: "subject" }),
},
纯生手写:
Vue-router
安装 npm vue-router
vue2中安装router3
vue3中安装router4
1.main.js中引入并使用插件:
import Vue from "vue";
import App from "./App.vue";
//引入vue-router
import VueRouter from "vue-router";
//引入router配置文件
import router from "./router";
Vue.config.productionTip = false;
//应用插件
Vue.use(VueRouter);
new Vue({
render: (h) => h(App),
router,
}).$mount("#app");
2.配置路由:
在router文件夹中创建index.js
//引入Vuerouter
import VueRouter from "vue-router";
//引入组件
import About from "../components/About.vue";
import Home from "../components/Home.vue";
//暴露
export default new VueRouter({
routes: [
{
path: "/about",
component: About,
},
{
path: "/home",
component: Home,
},
],
});
3.使用
<router-link to="/about">about</router-link>
<router-link to="/home">home</router-link>
<router-view></router-view>
嵌套路由
配置子路由
routes: [
{
path: "/about",
component: About,
},
{
path: "/home",
component: Home,
children: [
{
path: "news",
component: News,
},
],
},
],
使用:
<router-link to="/home/news">跳转News</router-link>
<router-view></router-view>
路由传参
query方式;
发送方:
<router-link
:to="{
path: '/home/news/detail',
query: {
id: item.id,
title: item.title,
},
}"
>信息{{ item.id }}</router-link
>
接收方:
<ol>
<li>{{ $route.query.id }}</li>
<li>{{ $route.query.title }}</li>
</ol>
params方式;
路由的props
路由replace
编程式路由导航
路由缓存
路由生命周期:
路由组件独有的生命周期钩子
activated
路由组件被激活时触发
deavtivated
路由组件失活时触发
路由守卫:
前置守卫,初始化时被调用
router.beforeEach((to,from,next)=>{})
后置守卫,路由切换后调用
router.afterEach((to,from)=>{})
独享路由守卫
beforeEnter: