组件传参
关于vue传参有三大类型
第一种:父向子传参(props)
父组件向子组件共享数据需要使用自定义属性----props
比如我们有父组件 Father 和 子组件 Son。如果需要父向子传参时,则需要在子组件Son中添加一个props(与data平级)。在props中可以添加自定义属性,属性名自己取。比如fromfather:{default:0, type:Number} 传参时只需要在父组件中使用子组件 这里使用的属性名必须与子组件中props上定义的一样
父组件的数据
<div class="box">
<p>这是父组件</p>
<son :list="list"></son>
</div>
通过props向子组件传参
子组件
props: {
//父组件传入的item数据
list: {
type: Object, //list类型
default: function () {
return {};
},
},
},
第二种:子向父传参($emit)
子组件向父组件共享数据使用自定义事件
在子组件Son的methods中定义一个方法,其中有this.$emit(‘自己定义的方法名’, 要传的数据)
<div class="right" @click="$emit('right-click', $event)">
//$emit的第一个参数即自定义的事件名,第二个参数是事件名对应的参数
第三种:兄弟组件之间传参
非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果。
第一步、创建bus.js文件
//导入Vue
import Vue from "vue"
//创建Vue实例
var bus = new Vue();
//导出bus
export default bus
第二步、在要发送数据的组件中导入bus
import bus from "@/utils/bus.js";
第三步、在有接受数据的组件中导入bus并使用bus.$on(注意this)
created() {
console.log(this.$children);
bus.$on("msgchange", ($event) => {
this.msg = $event;
});
},
这里需要注意:任意组件只要导入bus就可以随意的发送与监听数据
bus常用的三个方法
bus.$on(eventname,callback)监听事件
bus.$emit(eventname,data)发送事件
bus.$off(eventname)移除事件
还有一种特殊的依赖注入provider和inject(跨层级访问,只读)
provider提供数据,所有子组件都可以通过inject接受数据
inject接受父辈提供的数据
完整代码
<template>
<div class="nav" :style="{backgroundColor:bg_color,color:text_color}">
<div class="left" @click="$emit('left-click',$event)">
<slot name="icon_left"></slot>{{left_text}}
</div>
<div class="title">
<slot name="title"></slot>{{title}}
</div>
<div class="right" @click="$emit('right-click',$event)">
{{right_text}}
<slot name="icon_right"></slot>
</div>
<p :style="{'backgroundColor':myColor}" @click="$parent.outNum++">访问父组件outNum:{{$parent.outNum}}</p>
<p>来自APP组件:{{myMsg}}</p>
</div>
</template>
<style lang="scss" scoped>
.nav {
height: .88rem;
line-height: .88rem;
display: flex;
align-items: center;
font-size: .2rem;
.title {
flex: 1;
text-align: center;
}
.left,
.right {
padding: 0 .3rem;
}
}
</style>
<script>
import bus from '@/utils/bus.js'
export default {
created() {
bus.$on("msgchange", $event => {
console.log("msgchange");
this.myMsg = $event
})
},
data() {
return {
myColor: '#f30',
myMsg: ""
}
},
props: {
//文本颜色
text_color: {
type: String, default: "#000"
},
bg_color: { type: String, default: '#fff' },
//标题
title: { type: String, default: '' },
left_text: { type: String, default: "" },
right_text: { type: String, default: "" },
}
}
</script>
vuex 的概念
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
vuex核心概念:
vuex中有五个状态 State Getter Mutation Action Module
什么时候我们才使用Vuex呢
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
Vuex的优点
Vuex实现数据全局共享,响应式更新
为什么要把登录转换到vuex中
- 登录后成功的数据可以全局共享
- 为了重复利用,登录功能 不可能值在登录页面,如:
首页点击登录弹框按钮
购物车,跳转前,弹框登录,登录位置会有很多
如果写在vuex中,只需要在登录的地方调用$stroe.dispatch(“login”,data)就可以
html这是的一个vuex使用,可以看到存储在vuex里的数据,在不同的组件中都可以使用
//登录
<template>
<div id="">
<h1>登录</h1>
<input type="text" v-model="user.name" placeholder="请输入用户名"> <br>
<input type="password" v-model="user.password" placeholder="请输入密码"/> <br>
<button @click="$store.dispatch('login',user)">登录</button>
<p>
<router-link to="/reg">注册</router-link>
</p>
<button @click="$notify.show('该做核酸了!','pink')">自定义通知</button>
</div>
</template>
//注册
<template>
<div>
<h1>注册</h1>
<input type="text" v-model="user.name" placeholder="用户名:"> <br>
<input type="password" v-model="user.password" placeholder="密码:"> <br>
<button @click="$store.dispatch('reg',user)">注册</button>
</div>
</template>
为什么要写api/login.js实现登录
- 重复利用,登录的api也会调用很多次
- 方便集中管理所有的请求地址与请求方式api文件中
- 改请求方式与参数可以直接修改api内容就可以,不用具体进入到某个组件
import { Login, Reg } from '@/api/user.js'
import $router from "@/router/index.js"
import Notify from '@/plugin/Notify/index.js'
import Vue from 'vue'
Vue.use(Notify)
export default {
state: {
userInfo: {
name: "wang",
score: 50
},
token: ""//token标识
},
mutations: {
SET_USERINFO(state, data) {
//更新state的userinfo信息
state.userInfo = data;
//本地存储信息
localStorage.setItem("user", JSON.stringify(data))
},
SET_TOKEN(state, data) {
state.token = data;
//本地存储信息
localStorage.setItem("token", data)
},
},
actions: {
//页面退出
logout(context) {
context.commit("SET_USERINFO", {})
context.commit("SET_TOKEN", {})
// var $route = $router.history.current
// //获取查询参数
// var redirect = $route.query.redirect || '/';
// //实现跳转
$router.replace('/user')
},
//负责登录
login(context, data) {
Login(data)
.then(res => {
if (res.data.code === 200) {
Notify.success(res.data.msg || "登录成功")
alert(res.data.msg)
context.commit("SET_USERINFO", res.data.user)
context.commit("SET_TOKEN", res.data.token)
var $route = $router.history.current
//获取查询参数
var redirect = $route.query.redirect || '/';
//实现跳转
$router.replace(redirect)
} else {
//登录不成功清除用户信息
Notify.danger(res.data.msg || "登录失败")
// context.commit("SET_USERINFO", {})
// context.commit("SET_TOKEN", "")
alert(res.data.msg)
}
})
//失败显示网络失败
.catch(err => {
console.log(err);
alert("网络失败")
})
},
reg(context, data) {
Reg(data)
.then(res => {
if (res.data.code === 0) {
alert('注册成功')
Notify.success(res.data.msg || "注册成功")
$router.push('/login')
} else {
alert(res.data.msg || "注册失败")
Notify.push('/login')
}
})
.catch((err) => {
console.error(err);
})
}
}
}