// 写法1:
new Vue({el:'#root'
})
//写法2:挂载
vm.$mount('#root')
// 写法1:对象式
data:{name:'JOJO'
}
// 写法2:函数式(组件要用函数式)
data(){return{name:'JOJO'}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o0Uc1PxM-1678173707233)(img/img.png)]
methods:{showInfo1(event){console.log(event)},showInfo2(evnet,num){console.log(event,num)}
}
姓:
名:
姓名:{{fullName}}
//写法1:完整版
computed:{fullName:{get(){return this.firstName + '-' + this.lastName},set(value){const arr = value.split('-')this.firstName = arr[0]this.lastName = arr[1]}}
}
//写法2:函数版(简写)
computed:{fullName(){return this.firstName + '-' + this.lastName}}
总结:
今天天气好{{info}}!
// 写法1:
new Vue({el:'#root', data:{ isHot:true,},// 根据isHot的bool值决定显示什么文字computed:{info(){return this.isHot ? '炎热' : '凉爽' }},// 按钮点击改变isHot的值methods:{changeWeather(){this.isHot = !this.isHot}},// 监视isHot的值,要是改变了就输出watch:{isHot:{immediate:true, //初始化时让handler调用一下//handler什么时候调用?当isHot发生改变时handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}}}})
总结:
通过vm.$watch监视
// 写法2:
vm.$watch('isHot',{immediate:true,handler(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue)}
})
// 写法3:简写。如果监视属性除了handler没有其他配置项的话,可以进行简写。
isHot(newValue,oldValue){console.log('isHot被修改了',newValue,oldValue,this)
}
a的值是:{{numbers.a}}
b的值是:{{numbers.b}}
new Vue({el:'#root', data:{ isHot:true,numbers:{a:1,b:1,}},watch:{//监视多级结构中所有属性的变化numbers:{deep:true,handler(){console.log('numbers改变了')}},//监视多级结构中某个属性的变化'numbers.a':{handler(){console.log('a被改变了')}} }})
总结:
一、共同点:
v-if 和 v-show 都能实现元素的显示隐藏
二、区别:
三、v-show与v-if的使用场景
四种用法
https://blog.csdn.net/qq_39055970/article/details/106308347?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-106308347-blog-124694828.pc_relevant_landingrelevant&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-1-106308347-blog-124694828.pc_relevant_landingrelevant&utm_relevant_index=1
写法
局部
new Vue({ directives:{指令名:配置对象/回调函数} })
全局
Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
})
配置对象中常用的3个回调函数:
组件实例对象(vc)可以访问到 Vue 原型上的属性、方法
功能:让组件接收外部传过来的数据
传递数据:
接收数据:
第一种方式(只接收):props:[‘name’]
第二种方式(限制数据类型):props:{name:String}
第三种方式(限制类型、限制必要性、指定默认值):
props:{name:{type:String, //类型required:true, //必要性default:'JOJO' //默认值}
}
props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据
功能:可以把多个组件共用的配置提取成一个混入对象
定义混入:
const mixin = {data(){....},methods:{....}....
}
使用混入:
全局混入:Vue.mixin(xxx)
局部混入:mixins:['xxx']
作用:让样式在局部生效,防止冲突
写法:
存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制
相关API:
xxxStorage.setItem(‘key’, ‘value’):该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值
xxxStorage.getItem(‘key’):该方法接受一个键名作为参数,返回键名对应的值
xxxStorage.removeItem(‘key’):该方法接受一个键名作为参数,并把该键名从存储中删除
xxxStorage.clear():该方法会清空存储中的所有数据
备注:
一种组件间通信的方式,适用于:==子组件 > 父组件
使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)
绑定自定义事件:
...
mounted(){this.$refs.demo.$on('atguigu',data)
}
//安装全局事件总线:new Vue({...beforeCreate() {Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm},...
使用事件总线:
接收数据:A组件想接收数据,则在A组件中给bus绑定自定义事件,事件的回调留在A组件自身‘this.bus绑定自定义事件,事件的回调留在A组件自身`this.bus绑定自定义事件,事件的回调留在A组件自身‘this.bus.$on(‘xxx’,this.demo)`
提供数据:this.$bus.$emit('xxx',data)
最好在beforeDestroy
钩子中,用$off
去解绑当前组件所用到的事件
消息订阅与发布是一种组件间通信的方式,适用于任意组件间通信
使用步骤:
安装pubsub:npm i pubsub-js
引入:import pubsub from ‘pubsub-js’
接收数据:A组件想接收数据,则在A组件中订阅消息pubsub.subscribe('xxx',this.demo)
,订阅的回调留在A组件自身
提供数据:pubsub.publish('xxx',data)
最好在beforeDestroy
钩子中,使用pubsub.unsubscribe(pid)
取消订阅
this.$nextTick(回调函数)
作用:在插入、更新或移除 DOM元素时,在合适的时候给元素添加样式类名
写法:
元素进入的样式:
v-enter:进入的起点
v-enter-active:进入过程中
v-enter-to:进入的终点
元素离开的样式:
v-leave:离开的起点
v-leave-active:离开过程中
v-leave-to:离开的终点
使用包裹要过度的元素,并配置name属性:
你好啊!
有三种类型
默认插槽:在父组件中调用子组件,在子组件中插入结构,子组件中使用slot占位,父组件插入的结构会在子组件的slot里展示
父组件中:html结构1
子组件中:插槽默认内容...
具名插槽:使用方法同默认插槽,但需要写名字,子组件内使用name标识,在父组件中插入插槽元素需要使用template包裹,并在template中使用slot=名称,以适用对应的slot
父组件中:html结构1html结构2
子组件中:插槽默认内容... 插槽默认内容...
作用域插槽:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定
//父组件
{{g}} //子组件
data() {return {games:['红色警戒','穿越火线','劲舞团','超级玛丽']}
},
专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信
当多个组件依赖于同一状态,来自不同组件的行为需要变更同一状态需要使用vuex
操作:放在 src/store/index.js
当需要判断或者处理其他业务逻辑的时候放在actions(context,value)
里,当处理完毕以后通过context.commit('mutations名称',value)
把数据放到mutations里
mutations里进行对state里数据的操作,使用数据的时候需要state.数据名称
组件中读取vuex中的数据:$store.state.数据名称
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)//准备actions对象——响应组件中用户的动作
const actions = {addOdd(context,value){console.log("actions中的addOdd被调用了")if(context.state.sum % 2){context.commit('ADD',value)}},addWait(context,value){console.log("actions中的addWait被调用了")setTimeout(()=>{context.commit('ADD',value)},500)},
}
//准备mutations对象——修改state中的数据
const mutations = {ADD(state,value){state.sum += value},SUBTRACT(state,value){state.sum -= value}
}
//准备state对象——保存具体的数据
const state = {sum:0 //当前的和
}//创建并暴露store
export default new Vuex.Store({actions,mutations,state
})
在组件中使用,绑定方法,在方法中this.$store.commit('方法名称',传的值)
当前求和为:{{$store.state.sum}}
当前求和的10倍为:{{$store.getters.bigSum}}
概念:当state
中的数据需要经过加工后再使用时,可以使用getters
加工
在store.js
中追加getters
配置
组件中读取数据:$store.getters.bigSum
...const getters = {bigSum(state){return state.sum * 10}}//创建并暴露storeexport default new Vuex.Store({...getters})
mapState方法:用于帮助我们映射state
中的数据,取代一个个写$store,在组件中直接当作组件内变量使用
computed: {//借助mapState生成计算属性:sum、school、subject(对象写法)...mapState({sum:'sum',school:'school',subject:'subject'}),//借助mapState生成计算属性:sum、school、subject(数组写法)...mapState(['sum','school','subject']),
},
mapGetters方法:用于帮助我们映射getters
中的数据
computed: {//借助mapGetters生成计算属性:bigSum(对象写法)...mapGetters({bigSum:'bigSum'}),//借助mapGetters生成计算属性:bigSum(数组写法)...mapGetters(['bigSum'])
},
mapActions方法:用于帮助我们生成与actions
对话的方法,即:包含$store.dispatch(xxx)
的函数
methods:{//靠mapActions生成:incrementOdd、incrementWait(对象形式)...mapActions({组件内调用名称:'vuex中的函数名称'})
}
mapMutations方法:用于帮助我们生成与mutations
对话的方法,即:包含$store.commit(xxx)
的函数
methods:{//靠mapActions生成:increment、decrement(对象形式)...mapMutations({组件内调用名称:'vuex中的函数名称'}),
}
使用 const 名称来命名
读取的时候需要加上名称
const countAbout = {namespaced:true,//开启命名空间state:{x:1},mutations: { ... },actions: { ... },getters: {bigSum(state){return state.sum * 10}}
}const personAbout = {namespaced:true,//开启命名空间state:{ ... },mutations: { ... },actions: { ... }
}const store = new Vuex.Store({modules: {countAbout,personAbout}
})
先需要创建一个路由文件,把组件的路由填写进来,active-class
可配置高亮样式
src/router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from "vue-router";
//引入组件
import Home from '../components/Home'
import About from '../components/About'//创建并暴露一个路由器
export default new VueRouter({routes:[{path:'/about',component:About},{path:'/home',component:Home}]
})
通过router-link 创建导航栏,使用router-view占位,当路由跳转以后会在view里面展示
About
通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载
每个组件都有自己的$route
属性,里面存储着自己的路由信息
整个应用只有一个router,可以通过组件的$router
属性获取到
配置路由规则,使用children配置项
routes:[{path:'/about',component:About,},{path:'/home',component:Home,children:[ //通过children配置子级路由{path:'news', //此处一定不要写:/newscomponent:News},{path:'message', //此处一定不要写:/messagecomponent:Message}]}
]
跳转:News
两种传递参数方法
跳转
跳转
接收参数
$route.query.id
$route.query.title
目的是为了简化路由的写法,不用直接写路径
跳转
跳转
name:'hello',query:{id:666,title:'你好'}}"
>跳转 {path:'/demo',component:Demo,children:[{path:'test',component:Test,children:[{name:'hello' //给路由命名path:'welcome',component:Hello,}]}]
}
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
//路由写法
{component:Message,children:[{name:'xiangqing',path:'detail/:id/:title', //使用占位符声明接收params参数component:Detail}]}
//接收参数的其他写法
//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
props:{a:1,b:'hello'}
//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
props:true
//props的第三种写法,值为函数props($route){return {id:$route.params.id,title:$route.params.title,}}//组件写法
跳转
name:'xiangqing',params:{id:666,title:'你好'}}"
>跳转 //获取数据
//方法1:
消息编号:{{$route.params.id}}
消息标题:{{$route.params.title}}
//方法2:
props:['id','title']
作用: 不借助< router-link>实现路由跳转 让路由跳转更灵活,在router-link里填大配置,在编程式路由也可以填
this.$router.push({}) 内传的对象与中的to相同
this.$router.replace({}) 替换当前页记录跳转
this.$router.forward()前进
this.$router.back() 后退
this.$router.go(x) 指定步数跳转,当x为正数时,前进x步,当x为负数时,后退x步
作用:让不展示的路由组件保持挂载,不被销毁
//缓存一个路由组件
//include中写想要缓存的组件名,不写表示全部缓存
//缓存多个路由组件
activated
和deactivated
是路由组件所独有的两个钩子,用于捕获路由组件的激活状态
具体使用:
activated
路由组件被激活时触发deactivated
路由组件失活时触发分类:全局守卫、独享守卫、组件内守卫
全局守卫
//全局前置守卫:初始化时执行、每次路由切换前执行
router.beforeEach((to,from,next)=>{console.log('beforeEach',to,from)if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制if(localStorage.getItem('school') === 'atguigu'){ //权限控制的具体规则next() //放行}else{alert('暂无权限查看')}}else{next() //放行}
})//全局后置守卫:初始化时执行、每次路由切换后执行
router.afterEach((to,from) => {console.log('afterEach',to,from)if(to.meta.title){ document.title = to.meta.title //修改网页的title}else{document.title = 'vue_test'}
})
独享守卫:
beforeEnter(to,from,next){console.log('beforeEnter',to,from)if(localStorage.getItem('school') === 'atguigu'){next()}else{alert('暂无权限查看')}
}
组件内守卫:
//进入守卫:通过路由规则,进入该组件时被调用
beforeRouteEnter (to, from, next) {...},
//离开守卫:通过路由规则,离开该组件时被调用
beforeRouteLeave (to, from, next) {...},
对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值
hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器
hash模式:
地址中永远带着#号,不美观
若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法
兼容性较好
history模式:
地址干净,美观
兼容性和hash模式相比略差
应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题