【一】ref父子通信总结
1.1之前学过的
#1.放在普通标签上
#2.放在组件上
在js中用this.$refs.ref名获取该对象
1.2父传子
就是直接
this.$refs.组件的ref.属性=父组件的变量就可以直接传值了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue2/vue.js"></script>
</head>
<body>
<div id="app">
<h1>父亲拿到值{{username}}</h1>
<child ref="child"></child>
<button @click="senddata">点我子传父</button>
<button @click="sendson">点我父传子</button>
</div>
</body>
<script>
Vue.component('child', {
template: `
<div>我是子组件
{{this.getname}}
我是子组件
</div>
`,
data() {
return {
name: 'llh',
getname: ''
}
},
methods: {}
})
new Vue({
el: '#app',
data: {
username: 'llh',
},
methods: {
senddata() {
this.username = this.$refs.child.name
},
sendson(){
this.$refs.child.getname=this.username
}
}
})
</script>
</html>
1.3父传子
直接获取自组建的值
父组件属性=this.$refs.组件的ref.属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./vue2/vue.js"></script>
</head>
<body>
<div id="app">
<h1>父亲拿到值{{username}}</h1>
<child ref="child"></child>
<button @click="senddata">点我子传父</button>
</div>
</body>
<script>
Vue.component('child',{
template:`<div>我是子组件</div>`,
data(){
return{
name:'llh'
}
},
methods: {
}
})
new Vue({
el:'#app',
data:{
username:'',
},
methods:{
senddata(){
this.username=this.$refs.child.name
}
}
})
</script>
</html>
1.4补充-子组件中拿到父组件对象
# this.$parent但是这个一般不用因为如果有多个父组件呢
1.5总结:父子通信的方式
# 1 自定义属性
props
# 2 自定义事件
this.$emit('事件名',参数)
# 3 通过ref属性:this.$refs
# 4 子组件中通过 this.$parent
【二】props使用方式的总结
# props是用来父传子时,自定义属性,在子组件中声明,才能使用当前属性
#方式一:
props:['msg']
#方式二:限制类型--》如果传的不是string,那么也会可以运行但是会报警告,类似于python的弱类型
props:{myname:String}
#方式三:/默认值父亲没有name才会给默认值,若是空字符串那也是有值的
props:{
myname: {
type: String, //类型
required: true, //必要性
default: '老王'
}
【三】混入
# 1 抽取公共的代码,
-多个组件中都会有的代码,抽出来
-哪个组件用,使用mixin引入即可
"""注意,他导出的是共同代码,用的时候,类似于字典,无则新增,有则用原来的"""
#方式1,局部
1.在vue中的使用
import mixin from '@/mixin/llh'
export default {
data(){
return {name:'llh'}
},
methods:{
handleclick(username){
this.name="阿华"
}
},
mixins:[mixin]
}
2.js,混用文件
export default {
data(){
return {name:'llh'}
},
methods:{
handleclick(changename){
this.name=changename
}
}
}
#方式2全局使用---》可以多每个vue实例都用混用
import m1 from '@/mixin'
import m2 from '@/mixin2'
Vue.mixin(m1)
Vue.mixin(m2)
"""优先级:自己有》局部定义》全局"""
【四】插件
#1 功能:用于增强Vue
#2 本质:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
#3 使用了vue-router插件,vuex插件,elementui
this.$router this.$store this.$alert this.$message
# 4 使用别人写好的第三方插件
Vue.use(ElementUI);
"""$指令都在原型类中,类似于对象的继承,找不到就一层一层往父亲找"""
4.1自定义插件
#做一个axios的插件案例把这个指令变成长得和jquery很像的ajax请求
1.第一步:做一个插件
"""注意:
1.为了防止变量污染,所以我们一般都给插件的指令用的时候加$
2.那么就要给原型类加Vue.prototype
3.插件要导出用所以先来个导出"""
import axios from "axios";
export default {
install(Vue){
Vue.prototype.$ajax = axios Vue.prototype.$BASE_URL='http://127.0.0.1:8000/'
}
}
2.第二步:在main.js进行全局声明
//插件要先声明一下
import selfset from '@/plugin'
Vue.use(selfset)
3.第三步使用
handleclick(changename){
this.$ajax.get('http://192.168.1.108:8000/chatroom/').then(response=>{
alert("axios")
}).catch(error => {
console.error('请求失败:', error);
})
}
# 咱们需要掌握的;
-有些第三方插件,用了以后,增强了vue功能
-this.$router
-全局组件 :el-button
-this.$message--->
-this.$http.get
4.2自定义指令
1.定义全局指令:跟v-model一样,获取焦点
Vue.directive("v-bind", {
//指令与元素成功绑定时(一上来)
bind(element, binding) {
element.value = binding.value;
},
//指令所在元素被插入页面时
inserted(element, binding) {
element.focus();
},
//指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value;
},
});
【五】vuex
#1 第三方插件:状态管理器--》管理状态--》管理变量的---》统一的位置管理变量--》实现组件间通信
-vue2 :vuex
-vue3:vuex,pinia:用的多
# 2 使用vuex
-创建项目时候,已经装了
-项目依赖有了
-项目中有个 store文件夹-->index.js
-main.js 中,引入且使用了
-在创建项目时,没装
-安装:cnpm install vuex@3.6.2
cnpm install element-ui@2.15.13 -S
-在项目中新建 store--》index.js
-在index.js中写入代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
在main.js中使用
import store from './store'
new Vue({
store,
render: h => h(App)
}).$mount('#app')
# 3 具体使用
记住一个思想,类似于去点餐,三种方式
1.自己直接炒
2.直接叫厨师炒commit("函数名",参数)
3.通过服务员点单,服务员叫厨师炒dispatch("函数名",参数)
# 4 作用和好处
-1 降低代码耦合度
-2 实现组件间通信
5.1具体使用
1.在store里的index.js
export default new Vuex.Store({
//存原值
state: {
count:1
},
getters: {
getCount(state) {
return state.count + 100
}
},
mutations: {
//这里会自动传入state对象
add(state){
state.count++
}
},
//服务员--》调commit
actions: {
// ctx就是上下文,这里调用函数会自动传入一个上下文参数
add(ctx){
//通知厨师长炒菜
ctx.commit('add')
}
},
modules: {
}
})
2.在组件中调用
stateclick(){
#方式一:直接改,容易出问题,没有校验之类的
this.$store.state.count++
#方式二: 叫厨师直接炒,直接调用commit方法
this.$store.commit('add')
#方式三:一套流程
先告诉服务员dispatch--》他会自动调用commite叫厨师炒菜
this.$store.dispatch('add')
}
调用getters-->this.$store.getters.getCount
# 3 为什么经过 actions和mutations
-可以跟后端交互,可以做数据验证
# 8 getters:
可以通过getters获取数据--》对state中的数据,再做处理
# 9 modules:
分到不同模块中,不同模块有自己的state,actions
【六】本地存储
# 1 能存储数据的位置,登录成功---》token存储
vuex: 页面重新加载--》数据会恢复
cookie:登录信息放这里,有过期时间,一旦过期,就没了
sessionStorage:当前浏览器生效---》关闭浏览器,数据就没了
localStorage:永久生效,除非代码删除或清空浏览器缓存
-未登录,加购物车
#2 cookie 需要下载 vue-cookies
cnpm install vue-cookies -S
#在main.js要声明一下插件
import cookies from 'vue-cookies'
Vue.prototype.$cookies=cookies
1.vuex-->炒菜也能存但是页面重新加载--》数据会还原
2.localStorage
#存命令
localStorage.setItem("user", JSON.stringify(user))--》注意这个必须是一个字符串
#获取
localStorage.getItem('user')
#删
localStorage.removeItem('name')
localStorage.clear()
3.sessionStorage
#存命令
sessionStorage.setItem("name", '彭于晏')
#获取
sessionStorage.getItem('name')
#删
sessionStorage.removeItem('name')
sessionStorage.clear()
2.cookie
#存命令
this.$cookies.set('name', 'zzzz', '100s')--》注意这里的过期时间必须是1d,1m,1s,这样如果写数字,它就变成session关了就没了
#获取
this.$cookies.get('name')
#删
this.$cookies.remove('name')
【七】vue-router
# 1 如果我们创建项目时,已经安装了
-router--》index.js
-main.js 引入了
-后期在组件中:
-js中:
this.$router # 跳转路径
this.$route # 目前没学
-template中:
<router-view/> # 当访问某个路径时,会把页面组件替换到这
<router-link></router-link>
# 2 创建项目没有安装,自行引入
-创建文件夹router---index.js
-index.js写代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from "@/views/HomeView";
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
-main.js中使用
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
-后续所有组件中
-js中:
this.$router # 跳转路径
this.$route # 目前没学
-template中:
<router-view/> # 当访问某个路径时,会把页面组件替换到这
<router-link></router-link>
7.1 路由跳转
1.之前我们所知
<router-view/>通过路径切换组件
2.注册路径-->routes
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
"""这样做了以后访问某路径,就会切换到指定组件上"""
7.1.1路径跳转的方式(重点)
1.直接传路径
this.$router.push('/about')
2.可以传一个对象
this.$router.push({'path': '/about'})
this.$router.push({'name': 'about'})
3.携带参数跳转
this.$router.push('/about?name=lqz&age=19')
this.$router.push({'name': 'about',query:{name:'zhangsan',age:19}})
this.$router.push({'path': '/about',query:{name:'zhangsan',age:19}})
4.template中跳转:router-link组件--》类似导航栏
4.1直接传路径
<router-link to="/about">
<button>点我跳转到about页面-router-link</button>
</router-link>
4.2传对象
<router-link :to="{name:'about',query:{name:'xxx'}}">
<button>点我跳转到about页面-router-link</button>
</router-link>
5.取参数------------》重点
this.user1 = this.$route.query.参数名;
"""#route与router的区别"""
console.log(this.$router) // VueRouter 的对象
console.log(this.$route) // 当前路由对象
6."""若不是想之前的路由拼接,而是想之前的路径转换器一样/99/lqz"""
6.1 路由写法变了
{
path: '/:pk/lqz',
name: 'lqz',
component: LQZView
},
6.2 传递数据
-js:
this.$router.push("/99/lqz")
this.$router.push({name:'lqz',params:{pk:666}})
6.3router-link:
<router-link to="/99/lqz">
<router-link :to="{name:'lqz',params:{pk:666}}">---》注意这个to是一个属性变量了
6.4 另一个页面获取数据
this.$route.params.指定名字
this.$route.params.pk
7.2 相关api
1 指的是:this.$router--->方法
2 常用的
this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
this.$router.back(): 请求(返回)上一个记录路由
this.$router.go(-1): 请求(返回)上一个记录路由
this.$router.go(1): 请求下一个记录路由
7.3 多级路由
类似模板的block 把某些位置给固定,点击导航栏就只有中间变
"子路由的path路径前不能写/否则就会变成单独一个路径,就不是mul下的子路由了"
1.MulRouterView
<template>
<div>
<div style="height: 80px;background-color: pink"></div>
<el-container>
<el-aside width="200px">
<div style="background-color:greenyellow;height:700px ">
<p><router-link to="/mul/">首页</router-link></p>
<p><router-link :to="{name:'order'}">订单</router-link></p>
<p><router-link to="/mul/good">商品</router-link></p>
</div>
</el-aside>
<el-container>
<el-header>
<div style="background-color:rebeccapurple"></div>
</el-header>
<el-main>
<div style="height:500px;background-color: aqua">
<router-view></router-view>
</div>
</el-main>
<el-footer>
<div style="background-color: pink;height:50px"></div>
</el-footer>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "MulRouterView"
}
</script>
<style scoped>
</style>
2.路由
{
path:'/mul',
name:'mul',
component: MulRouterView,
children:[
{
path:'',
name:'index',
component: IndexView,
},{
path:'good',
name:'good',
component: GoodView,
},{
path:'order',
name:'order',
component: OrderView,
},
]
}
3 .IndexView.vue--->order和goods与这一样就改个h1里的字
<template>
<div>
<h1>后台首页</h1>
</div>
</template>
<script>
export default {
name: "IndexView"
}
</script>
<style scoped>
</style>
7.4路由守卫
# 1 路由守卫是什么
从名字可以得出就是守护路由看你有没有资格去访问
eg:你没登陆可以访问某页面,登录了可以访问某页面
# 2 全局守卫、独享守卫、组件内守卫
一般我们只用全局守卫
#1. to: 要去的路由对象
#2. from:来自哪个路由对象
#3. next:跳转到某个路径
#4. 要去的路径,如果不是/login或 / 就要判断有没有登录【登录后token保存到localStorage中了】
"""注意如果不是在vue文件中用相关的组件,那么要自己重新导入一下
import cookies from 'vue-cookies'
import Element from 'element-ui';
"""
router.beforeEach((to, from, next) => {
if(to.name=='login' ||to.name=='register'){
next()
}else{
console.log(cookies.get('token'))
if(cookies.get('token')){
next()
}else{
Element.Message.error('您没有登录,请先登录')
this.router.push({name:'login'})
}
}
})
7.4路由的两种工作模式
# 1 对于一个url来说,什么是hash值?—— # 及其后面的内容就是hash值
# 2 hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
# 3 hash模式:
地址中永远带着#号,不美观 。
若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
兼容性较好
# 4 history模式:
地址干净,美观 。
兼容性和hash模式相比略差。
应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题-->
因为后端服务器只有一个首页的地址,所以多了其他的路径就会报找不到路径404的错