vue create 项目名称
//vue.config.js
modules.exports = {
pages:{
index:{
//入口
entry:'/src/main.js'
},
},
lintOnSave:false,//关闭语法
}
更多修改默认配置:https://cli.vuejs.org/zh/config/
被用来给元素或子组件注册引用信息(id的替代者)
引用的html标签上虎丘的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
<div v-ref="b1">div>
console.log(this.refs.b1)
//父组件
<Student :name="name"/>
data(){
return{
name:'张三'
}
}
//子组件
<div>{{name}}</div>
props:['name']//简单接收
props:{
name:'String'
}
props:{
name:{
type:'String',
required:true,//必要的
default:'李四',//默认值
}
}
场景需求:如果想要修改props里面的值,做法如下:
props的优先级比data的优先级高
//父组件
<Student :age="age"/>
data(){
return{
age:18
}
}
//子组件
<div>{{age}}</div>
props:['age'],//简单接收
data(){
return{
myage:this.age
}
},
methods:{
addage(){
this.myage++
}
}
功能:让组件接收外部传过来的数据
备注:props是只读的,vue底层会检测你对props的修改。如果进行了修改,就会发出警告,若业务需求需要修改,那么请赋值props的内容到data中一份。然后去修改data中的数据
props适用于:父传子+子传父(要求父先给子一个函数)
功能:可以把多个组件共有的配置提取成一个混入对象
用处一:假设父组件和子组件公用一个接口请求数据
官方推荐Minxin应该用于插件开发,不建议应用使用
功能:用于挣钱vue
本质:包含install方法的一个对象,install的第一个参数是vue,第二个以后的参数是插件使用者传递的数据
app.vue 不适用
作用:让样式在局部生效,防止冲突
使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的
props传过来的若是对象类型的值,修改对象中的属性时vue不会报错,但不推荐这样做
两者统称为webStorage
//localStorage:本地存储
//保存
let p = {name:'jery'}
localStorage.setItem('person',JSON.stringify(p))
//读取
//如果要是读取的值获取不到则返回null
localStorage.getItem('person')
//删除
localStorage.removeItem('person')
//清空
localStorage.clear()
//localStorage特点:关闭浏览器不会清除数据-用户点击按钮清除会清除数据/清除缓存也会清除数据
//sessionStorage:会话存储
//保存
let p = {name:'jery'}
sessionStorage.setItem('person',JSON.stringify(p))
//读取
//如果要是读取的值没有则返回null
sessionStorage.getItem('person')
//删除
sessionStorage.removeItem('person')
//清空
sessionStorage.clear()
//sessionStorage特点:关闭浏览器会清除数据
数据在哪里,操作的数据方法就在哪里
//父组件
<school :getSchoolName="getSchoolName"/>
getSchoolName(name){
console.log('父组件收到',name)
}
//子组件
props:['getSchoolName']
getname(value){
this.getSchoolName(value)
}
//父组件
//点击触发
<school @getName="getSchoolName"/>
//只能点击一次
<school @getName.once="getSchoolName"/>
getSchoolName(name){
console.log('父组件收到',name)
}
//子组件
<div @click="getbutton">name</div>
data(){
return{
name:''
}
}
getbutton(){
this.$emit('getName',this.name)
}
//父组件
<school ref="student"/>
methods:{
getschoolname(){
}
},
mounted(){
//点击触发
this.$refs.student.$on('getname',this.getschoolname)
//只能点击一次
this.$refs.student.$once('getname',this.getschoolname)
this.$refs.student.$once('getname',((name)=>{
this.searchname = name
}))//必须写箭头函数
}
//子组件
<div @click="getbutton">name</div>
data(){
return{
name:''
}
}
getbutton(){
this.$emit('getschoolname',this.name)
}
解绑事件:给谁绑定就去谁那解绑
//子组件
unbind(){
this.$off('getschoolname')//解绑一个自定义事件
this.$off(['getschoolname','第二个'])//解绑多个自定义事件
this.$off()//解绑所有自定义事件
}
death(){
this.$destroy()//销毁了当前student组件的实例,销毁后所有student的自定义事件全部不奏效
}
props
//父组件
<school :getname="getname"/>
//子组件
props:[getname]
任意组件间通信
//main.js
new Vue({
el:'#app',
render:h=>h(App),
beforeCreate(){
Vue.prototype.$bus = this //安装全局事件总线,$bus就相当于当前应用的vm
}
})
//兄弟1
mounted(){
this.$bus.$on('hello',(data)=>{
console.log('我是组件1,收到了数据',data)
})
},
beforeDestroy(){
this.$bus.$off('hello')
}
//兄弟2
methods:{
send(){
this.$bus.$emit('hello',666)
}
}
最好在beforeDestroy钩子中,用$off去解绑当前组件所用到的事件
一种组件间通信的方式,适用于任意组件间通信
//收数据的人
import pubsub from 'pubsub-js'
mounted(){
this.pubId = pubsub.subscribe('hello',(消息名称,传的数据)=>{
console.log('有人发布了消息')
})
}
//如果不用参数可以用_占位
beforeDestroy(){
pubsub.unsubscribe(this.pubId)
}
//传数据的
import pubsub from 'pubsub-js'
methods:{
send(){
pubsub.publish('hello',666)
}
}
作用:在插入、更新或移除dom元素时,在合适的时候给元素添加样式类名
<transition name="hello" appear>
<h1 v-show="isShow">h1>
transition>
//第一种写法
.hello-enter-active{
animation:atguigu .5s liner
}
.hello-leave-active{
animation:atguigu .5s liner reverse
}
@keyframes atguigu{
from{
transform:translateX(-100%)
}
to{
transform:translateX(0px)
}
}
//第二种写法
.hello-enter{
transform:translateX(-100%)
}//进入的起点
.hello-enter-to{
transform:translateX(0)
}//进入的终点
.hello-leave-active,.hello-enter-active{
transiton:.5s liner;
}
.hello-leave{
transform:translateX(0)
}//离开的起点
.hello-leave-to{
transform:translateX(-100%)
}//离开的终点
transition标签内部只能有一个元素
如果多个元素过渡transition-group
需要注意的是transition-group里面的每一个元素都需要有一个key值
<transition-group>
<div key="1">div>
<div key="2">div>
transition-group>
animate.css
https://animate.style/
import 'animate.css'
//animate__shakeY这个是复制过来的
<transition-group
name="animate__animated animate__bounce"
enter-active-class="animate__shakeY"
leave-active-class="animate__headShake">
transition-group>
如果引入的第三方插件里面有没有用到的东西就不能用import引入 因为import是严格检查 直接在index.html里面引入即可
了解即可vue1.0的时候用的多
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于父组件—》子组件
分类:默认插槽、具名插槽、作用域插槽
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定
概念:专门在vue中实现集中式状态(数据)管理的一个vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
什么时候用vuex:
- 多个组件依赖同一个状态
- 来自不同组件的行为需要变更同一个状态
版本:
- vue2中要用vuex3版本
- vue3中要用vuex4版本
//main.js
import Vue from 'vue'
import store from './store/index'
new Vue({
store
})
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const actions = {//做业务逻辑处理
jisOdd(context,value){
if(context.state.sum%2){
context.comit('JIA',value)
}
}
}
const mutations = {//直接根开发者工具交流
//如果无业务逻辑可以直接写在mutations里面
JIA(state,value){
state.sum+=value
}
}
const state = {
sum:0
}
const getter = {//对state修改---类似计算属性
bigsum(state){
return state.sum*10
}
//获取this.$store.getters.bigsum
}
export default new Vuex.store({
actions,
mutations,
state ,
getter
})
//用的组件
data:{
return(){
n:1
}
}
methods:{
jia(){
this.$store.commit('jia',this.n)
//commit---mutations
},
jisOdd(){
this.$store.dispatch('jisOdd',this.n)
//dispatch----actions
}
}
//mapGetters写法和mapState同样
import {mapState,mapGetters} from 'vuex'
computed:{
...mapState({sum:'sum'})//借助mapstate生成计算属性,从state中读取数据(对象写法)
...mapState(['sum']})//(数组写法)
}
<div>{{sum}}=={{$store.state.sum}}div>
//mapActions与mapMutations写法一样
import {mapActions,mapMutations} from 'vuex'
methods:{
...mapMutations({increment:'JIA'})//借助mapMutations生成对应的方法,方法中会调用commit去练习mutations(对象写法)
...mapMutations(['JIA']})//(数组写法)
}
<div @click="increment(n)">对象写法div>
<div @click="JIA(n)">数组写法div>
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const countOptions = {
namespaced:true,//写这个属性可以在mapstate里面写成以下
//格式:...mapState('countAbout',['sum','school','subject'])
actions : {//做业务逻辑处理
jisOdd(context,value){
if(context.state.sum%2){
context.comit('JIA',value)
}
}
}
mutations : {//直接根开发者工具交流
//如果无业务逻辑可以直接写在mutations里面
JIA(state,value){
state.sum+=value
}
}
state : {
sum:0
}
getter : {//对state修改---类似计算属性
bigsum(state){
return state.sum*10
}
//获取this.$store.getters.bigsum
}
}
const person = {
namespaced:true,
state:{},
mutations:{
ADD_PERSON(state,value){
state.personList.unshift(value)
}
},
actions:{
addPersonWang(context,value){
if(value.name.indexOf('王')===0){
context.commit('ADD_PERSON',value)
}
}
},
state:{
personList:[]
},
getters:{
firstPersonName(state){
return state.personList[0].name
}
}
}
export default new Vuex.store({
modules:{
countAbout:countOptions ,
personAbout:person
}
})
//组件
import {mapState} from 'vuex'
computed:{
...mapState('countAbout',['sum'])//如果有多个就再写个
...personAbout('personAbout',['personList'])
personStateFirst(){
return this.$store.$getters['personAbout/firstPersonName']
}
},
methods:{
...mapMutations('personAbout',{increment:'JIA'})//
add(){
this.$store.commit('personAbout/ADD_PERSON',personObj)
}
addWang(){
this.$store.dispatch('personAbout/addPersonWang',personObj)
}
}
<div>{{sum}}div>
<div>{{personList.length}}div>
vue-router默认版本是4只能在vue3中应用
所以用vue2的时候下载vue-router版本应为3
- 路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹
- 通过切换,隐藏了的路由组件,默认是被销毁掉的,需要的时候再去挂载
- 每个组件都有自己的$route属性,里面存储着自己的路由信息
- 整个应用只有一个router,可以通过组件的$router属性获取到
<router-link replace to="">router-link>
作用:可以简化路由的跳转
对象写法:死数据,一般不用
第二种方法 只能params query不允许
第三种写法
作用:不借助router-link实现路由跳转,让路由跳转更加灵活
保留页面的记录
作用:让步暂时的路由组件保持挂载,不被销毁
注意:include写的是组件名的name
作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态
- 作用:对路由进行权限控制
- 分类:全局守卫、独享守卫、组件内守卫
只对一个路由做限制
酌情使用KeepAlive缓存组件状态
过度使用会造成内存泄漏
什么时候使用呢?
默认情况下,一个组件实例在被替换掉后会被销毁。这会导致它丢失其中所有已变化的状态——当这个组件再一次被显示时,会创建一个只带有初始状态的新实例。
也就是说,当你想要切换时,再回到这个页面的时候依然保留切换时的状态(例如分页)的时候使用
<keep-alive>
<router-view v-if=“$route.meta.keepAlive”>router-view>
keep-alive>
另外KeepAlive还支持配置最大缓存实例数来限制最大可以缓存的组件实例数。 如果缓存实例的数量即将超过指定的最大数量,则最长时间未访问的缓存实例将被销毁,以便为新实例腾出空间。
<KeepAlive :max=“10”>
<component :is=“activeComponent” />
KeepAlive>
当if-else逻辑过于复杂时,可以使用动态组件来实现,避免代码臃肿和可读性下降。 使用动态组件可以使代码组织得更清晰,组件重用,避免代码冗余。 这是示例代码:
<template>
<component :is=“componentName”>component>
template>
import Foo from “./Foo.vue”;
import Bar from “./Bar.vue”;
export default {
data() {
return {
componentName: “”,
};
},
mounted() {
if (condition) {
this.componentName = “Foo”;
} else {
this.componentName = “Bar”;
}
},
components: {
Foo,
Bar,
},
};