机关公文写作网站,设计师每天都上的网站,仿木鱼网络网站,微信网站制作免费文章目录 组件间传递消息props(子父组件之间传值)自定义事件(子父组件通信方式)全局事件总线(任意两个组件之间的通信)消息的订阅与发布(任意两个组件之间的传值) mixin混入plugin插件scoped样式WebStorage(浏览器存储)axiosslot插槽默认插槽具名插槽作用域插槽 Vuex将vuex中的… 文章目录 组件间传递消息props(子父组件之间传值)自定义事件(子父组件通信方式)全局事件总线(任意两个组件之间的通信)消息的订阅与发布(任意两个组件之间的传值) mixin混入plugin插件scoped样式WebStorage(浏览器存储)axiosslot插槽默认插槽具名插槽作用域插槽 Vuex将vuex中的属性和方法放到组件中去模块化命名空间(就是多个组件共享在vuex中定义的属性和方法)在store创建两个组件的js和index.js创建两个组件 main.js和app.vue 路由Vue Router简单使用案例多级路由路由query传参命名路由路由params传参路由中使用props传递和接收参数使浏览器没有路由点击的历史记录编程式路由导航缓存路由组件路由组件触发和失活的两个钩子 路由守卫全局路由守卫独享路由守卫组件内路由守卫 路由器的两种工作模式Vue UI组件库 组件间传递消息
props(子父组件之间传值)
三种写法 1.props:[‘name’] 2.props:{name:String} 3.限制类型、限制必要性、指定默认值
props:{name:{type:String, //类型required:true, //必要性default:JOJO //默认值}
}父组件 子组件 通信 子组件 父组件 通信要求父组件先给子组件一个函数
注意传入对象时 School :mmtodos/School todos是一个对象,如果mm前面不加 : 就会传成一个字符串. 注意尽量让传递的变量名和被传递的对象名一致: School :todostodos/School 传入方法时School :ccshowdata /School showdate是一个方法,如果showdata前面不加 : 就会传成一个字符串. 注意尽量让传递的变量名和被传递的对象名一致: School :showdatashowdata /School
使用v-model时要切记v-model绑定的值不能是props传过来的值因为props是不可以修改的 props传过来的若是对象类型的值修改对象中的属性时Vue不会报错但不推荐这样做
例: src\App.vue
templatediv idappSchool msg原来是风啊/School/div
/template
script
import School from ./components/School.vue
export default {name: App,components: {School}
}
/scriptsrc\components\School.vue
templatedivdiv{{name}}/divdiv{{age}}/divdiv{{msg}}/div/div
/template
script
export default {name: Vue1School,props:[msg],data() {return {name: 李四,age: 11};},
};
/script自定义事件(子父组件通信方式)
注意通过this. r e f s . x x x . refs.xxx. refs.xxx.on(‘atguigu’,回调)绑定自定义事件时回调要么配置在methods中要么用箭头函数否则this指向会出问题 若想让自定义事件只能触发一次可以使用once修饰符或$once方法
解绑自定义事件this.$off(atguigu)例: App.vue
templatediv classapp!-- 通过父组件给子组件绑定一个自定义事件实现子给父传递数据第一种写法使用或v-on --Student sendStudentgetStudentName refschool//div
/templatescriptimport Student from ./components/Student.vueimport School from ./components/School.vueexport default {name:App,components: { Student,School },mounted(){// 通过父组件给子组件绑定一个自定义事件实现子给父传递数据第二种写法使用ref this.$refs.school.$on(sendSchool,this.getSchoolName)},methods:{getStudentName(name){// 通过父组件给子组件绑定一个自定义事件实现子给父传递数据第一种写法使用或v-onconsole.log(已收到学生的姓名name) },getSchoolName(name){// 通过父组件给子组件绑定一个自定义事件实现子给父传递数据第二种写法使用ref console.log(已收到学校的名称name)}}}
/scriptStudent.vue
templatediv classstudenth2学生姓名{{name}}/h2h2学生性别{{sex}}/h2button clicksendStudent点我传递学生姓名/button button clicksendSchool点我传递学校姓名/button /div
/templatescriptexport default {name:Student,data() {return {name:JOJO,sex:男}},methods:{sendStudent(){this.$emit(sendStudent,大学生)},sendSchool(){this.$emit(sendSchool, 超级大学)}}}
/script全局事件总线(任意两个组件之间的通信)
全局事件总线是一种可以在任意组件间通信的方式本质上就是一个对象。它必须满足以下条件
1. 所有的组件对象都必须能看见他
2. 这个对象必须能够使用$on、$emit和$off方法去绑定、触发和解绑事件School.vue组件想接收数据则在School.vue组件中给$bus绑定自定义事件事件的回调留在School.vue组件自身
export default {methods(){demo(data){...}}...mounted() {this.$bus.$on(xxx,this.demo)}
}Student.vue提供数据this.$bus.$emit(xxx,data)
最好在beforeDestroy钩子中用$off去解绑当前组件所用到的事件例: 在main.js中安装全局事件总线
import Vue from vue
import App from ./App.vueVue.config.productionTip false
new Vue({render: h h(App),beforeCreate() {Vue.prototype.$bus this //安装全局事件总线}
}).$mount(#app)创建接收消息的组件: School.vue
templatediv classschoolh2学校名称{{name}}/h2h2学校地址{{address}}/h2/div
/templatescriptexport default {name:School,data() {return {name:尚硅谷,address:北京,}},methods:{demo(data) {console.log(我是School组件收到了数据,data)}},mounted() {this.$bus.$on(demo,this.demo)},beforeDestroy() {this.$bus.$off(demo)},}
/script创建发送消息的组件: Studen.vue
templatediv classstudenth2学生姓名{{name}}/h2h2学生性别{{sex}}/h2button clicksendStudentName把学生名给School组件/button/div
/templatescriptexport default {name:Student,data() {return {name:张三,sex:男}},methods: {sendStudentName(){this.$bus.$emit(demo,this.name)}}}
/script消息的订阅与发布(任意两个组件之间的传值)
发布 接收消息 订阅 发送消息 1.安装pubsubnpm i pubsub-js 2.在所有接收消息组件和发送消息组件中导入: import pubsub from ‘pubsub-js’ 3.发送消息组件: pubsub.publish(‘发布函数别名’,data) 4.接收消息组件
export default {//第一参数是methods(fucname,data){demo(data){...}}...mounted() {this.pid pubsub.subscribe(发布函数别名(和发送组件中保持一至),this.demo)}
}5.在接收消息组件中最好在beforeDestroy钩子中使用pubsub.unsubscribe(pid)取消订阅 例 接收消息方 src\components\Receive.vue
script
import pubsub from pubsub-js
export default {name: vueReceive,data() {return {};},mounted(){//定义需要其他组件需要传递参数的函数this.pubId pubsub.subscribe(aaaabbb,this.demo)},methods: {//接收消息函数demo(msgName,data) {console.log(接收到的消息为,data);console.log(msgName,data);}},beforeDestroy() {pubsub.unsubscribe(this.pubId) //取消订阅}
};
/script发送消息方 src\components\Send.vue
templatedivbutton clicksendMsgSend/button/div
/templatescript
import pubsub from pubsub-jsexport default {name: vueSend,data() {return {name: 李四};},methods: {sendMsg(){pubsub.publish(aaaabbb,this.name) //发布消息}},
};
/scriptmixin混入
全局混入Vue.mixin(xxx) 局部混入mixins:[‘xxx’]
1.组件和混入对象含有同名选项时这些选项将以恰当的方式进行“合并”在发生冲突时以组件优先。 2.同名生命周期钩子将合并为一个数组因此都将被调用。另外混入对象的钩子将在组件自身钩子之前调用。 1.局部混入: mixin.js
export const mixin {methods: {showName() {alert(this.name)}},mounted() {console.log(你好呀~)}
}School.vue
templatedivdiv{{name}}/divdiv{{age}}/divdiv{{msg}}/divbutton clickshowNameaaa/buttonbutton clickfuncbbb/button/div
/templatescript
import { mixin } from ../mixin;
export default {name: Vue1School,props:[msg],data() {return {name: 李四,age: 11};},methods:{func(){alert(hello)}},mounted(){console.log(world)},mixins:[mixin]
};
/script全局混入Vue.mixin(xxx)
import Vue from vue
import App from ./App.vue
//注意要加大括号
import {mixin} from ./mixin
Vue.mixin(mixin)Vue.config.productionTip false
new Vue({render: h h(App),
}).$mount(#app)plugin插件
1.功能用于增强Vue 2.本质包含install方法的一个对象install的第一个参数是Vue第二个以后的参数是插件使用者传递的数据 3.定义插件
plugin.install function (Vue, options) {// 1. 添加全局过滤器Vue.filter(....)// 2. 添加全局指令Vue.directive(....)// 3. 配置全局混入Vue.mixin(....)// 4. 添加实例方法Vue.prototype.$myMethod function () {...}Vue.prototype.$myProperty xxxx}4.使用插件Vue.use(plugin)
plugin.js
export default {install(Vue,x,y,z){console.log(x,y,z)//全局过滤器Vue.filter(mySlice,function(value){return value.slice(0,1)})//定义混入Vue.mixin({data() {return {x:100,y:200}},})//给Vue原型上添加一个方法vm和vc就都能用了Vue.prototype.hello (){alert(你好啊)}}
}使用插件 main.js
import Vue from vue
import App from ./App.vue
import plugin from ./plugin
import {mixin} from ./mixin
Vue.mixin(mixin)Vue.use(plugin,1,2,3)Vue.config.productionTip false
new Vue({render: h h(App),
}).$mount(#app)School.js
templatedivdiv{{name | mySlice}} /divdiv{{age}}/divdiv{{msg}}/divdiv{{x}}/divdiv{{y}}/divbutton clickshowNameaaa/buttonbutton clickfuncbbb/button/div
/templatescriptexport default {name: Vue1School,props:[msg],data() {return {name: 李四,age: 11};},methods:{func(){//使用插件中定义的函数this.hellow()}},mounted(){console.log(world)}
};
/scriptscoped样式
使样式局部生效
style scopedWebStorage(浏览器存储)
LocalStorage存储的内容需要手动清除才会消失 SessionStorage存储的内容会随着浏览器窗口关闭而消失
存储内容大小一般支持5MB左右不同浏览器可能不一样 浏览器端通过Window.sessionStorage和Window.localStorage属性来实现本地存储机制 相关API xxxStorage.setItem(‘key’, ‘value’)该方法接受一个键和值作为参数会把键值对添加到存储中如果键名存在则更新其对应的值 xxxStorage.getItem(‘key’)该方法接受一个键名作为参数返回键名对应的值 xxxStorage.removeItem(‘key’)该方法接受一个键名作为参数并把该键名从存储中删除 xxxStorage.clear()该方法会清空存储中的所有数据
xxxStorage.getItem(xxx)如果 xxx 对应的 value 获取不到那么getItem()的返回值是null JSON.parse(null)的结果依然是null
LocalStorage:例:
templatedivbutton clicksaveDate()点我保存数据/buttonbr/button clickreadDate()点我读数据/buttonbr/button clickdeleteDate()点我删除数据/buttonbr/button clickdeleteAllDate()点我清空数据/buttonbr//div
/templatescript
export default {name: Vue1School,data() {return {person:{name: 张三,age: 18}};},methods: {saveDate(){localStorage.setItem(msg,localStorage)localStorage.setItem(person,JSON.stringify(this.person)) },readDate(){console.log(localStorage.getItem(msg))console.log(localStorage.getItem(person))},deleteDate(){localStorage.removeItem(msg)localStorage.removeItem(person)},deleteAllDate(){localStorage.clear()}},
};
/scriptSessionStorage: 例:
templatedivbutton clicksaveDate()点我保存数据/buttonbr/button clickreadDate()点我读数据/buttonbr/button clickdeleteDate()点我删除数据/buttonbr/button clickdeleteAllDate()点我清空数据/buttonbr//div
/templatescript
export default {name: Vue1Student,data() {return {person:{name: 张三,age: 10}};},methods: {saveDate(){sessionStorage.setItem(msg,sessionStorage)sessionStorage.setItem(person,JSON.stringify(this.person))},readDate(){console.log(sessionStorage.getItem(msg))const person sessionStorage.getItem(person)console.log(JSON.parse(person))},deleteDate(){sessionStorage.removeItem(msg)sessionStorage.removeItem(person)},deleteAllDate(){sessionStorage.clear()}},
};
/scriptaxios
说一下为什么要配置代理服务器 1.首先浏览器从一个域名的网页去请求另一个域名的资源时域名、端口、协议任一不同都是跨域 2.但是服务器访问服务器是没有跨域的。所以在vue2中配置代理服务器就是将axios发的请求发送到前段vue2脚手架的服务器上让前端服务器去访问后端服务器就没有跨域问题了。 3.**具体操作**在vue.config.js文件中配置devServer后前段启动的服务器的地址的端口号就是代理服务器的端口号换个话说就是前端服务器就是代理服务器所以直接在axios中不直接请求后端服务器的具体地址和端口号应直接访问代理服务器前端服务器的端口号然后由代理服务器转发到后端服务器 1.下载axios库 npm install axios 2.配置代理服务器 方式一在vue.config.js中添加如下配置
devServer:{proxy:http://localhost:5000
}优点配置简单请求资源时直接发给前端即可 缺点不能配置多个代理不能灵活的控制请求是否走代理 工作方式若按照上述配置代理当请求了前端不存在的资源时那么该请求会转发给服务器 优先匹配前端资源
方式二在vue.config.js中添加如下配置详细配置
devServer: {proxy: {/api1: { // 匹配所有以 /api1开头的请求路径target: http://localhost:5000,// 代理目标的基础路径changeOrigin: true,pathRewrite: {^/api1: }},/api2: { // 匹配所有以 /api2开头的请求路径target: http://localhost:5001,// 代理目标的基础路径changeOrigin: true,pathRewrite: {^/api2: }}}
}// changeOrigin设置为true时服务器收到的请求头中的host为localhost:5000
// changeOrigin设置为false时服务器收到的请求头中的host为localhost:8080优点可以配置多个代理且可以灵活的控制请求是否走代理 缺点配置略微繁琐请求资源时必须加前缀
3.使用代理服务器 例如 vue.config.js中 devServer:{//代理服务器端口号port:7878,proxy:http://localhost:8888
}app.vue中
templatediv idrootbutton clickgetStudents获取学生信息/buttonbr//div
/templatescriptimport axios from axios export default {name:App,methods: {getStudents(){//直接想代理服务器端口发送请求axios.get(http://localhost:7878/fs).then(response {console.log(请求成功了,response.data)},error {console.log(请求失败了,error.message)})}}}
/scriptslot插槽
让父组件可以向子组件指定位置插入html结构也是一种组件间通信的方式
默认插槽
父组件中
Categorydivhtml结构1/div
/Category子组件中
templatedivslot插槽默认内容.../slot/div
/template例: Apple.vue
templatediv classcategoryh3{{title}}分类/h3!-- 定义一个插槽挖个坑等着组件的使用者进行填充 --slot我是一些默认值当使用者没有传递具体结构时我会出现/slot/div
/templateapp.vue
templatediv classcontainerApplediv{{ games[0] }}/div/AppleApplediv{{ games[1] }}/div/AppleApplediv{{ games[2] }}/div/Apple/div
/templatescript
import Apple from ./components/Appleexport default {name:App,components:{Apple},data() {return {games:[植物大战僵尸,空洞骑士,王国]}},}
/script具名插槽
父组件中
Categorytemplate slotcenterdivhtml结构1/div/templatetemplate v-slot:footerdivhtml结构2/div/template
/Category子组件中
templatedivslot namecenter插槽默认内容.../slotslot namefooter插槽默认内容.../slot/div
/template例 Apple.vue
templatedivslot nameaaa我是一些默认值当使用者没有传递具体结构时我会出现/slotslot namebbb我是一些默认值当使用者没有传递具体结构时我会出现/slot/div
/templateapp.vue
templatediv classcontainerApplediv slotbbbbbb/divdiv slotaaaaaa/div/Apple/div
/template作用域插槽
数据在组件的自身但根据数据生成的结构需要组件的使用者来决定。games数据在Category组件中但使用数据所遍历出来的结构由App组件决定
例 Apple.vue
templatedivslot :aaaaaa我是一些默认值当使用者没有传递具体结构时我会出现/slot /div
/template
script
export default {name: Vue1Apple,data() {return {aaa: 李四};},
};
/scriptapp.vue
templatediv classcontainerAppletemplate slot-scopemydatap{{ mydata.aaa }}/p/template/Apple/div
/templatescript
import Apple from ./components/Appleexport default {name:App,components:{Apple}}
/scriptVuex
使用Vuex步骤 1.下载Vuexnpm i vuex 2.创建src/store/index.js
//引入Vue核心库
import Vue from vue
//引入Vuex
import Vuex from vuex
//应用Vuex插件
Vue.use(Vuex)//mutations的强化版mutations不可异步修改states但是actions可以做到所以actions用于异步修改数据$store.dispatch(action中的方法名,数据) 可以在action中发送接收请求
const actions {}
//相当于页面中的method即修改数据的方法但是只有通过mutations才能修改states中的数据$store.commit(mutations中的方法名,数据)若没有网络请求或其他业务逻辑组件中也可以越过actions即不写dispatch直接编写commit
const mutations {}
//我们需要全局使用的数据 $store.state.xxx (xxx是state中的一个数据)
const state {}
//类似于计算属性但可以全局调用
const getters {}//创建并暴露store
export default new Vuex.Store({actions,mutations,state,getters
})3.在src/main.js中配置
import Vue from vue
import App from ./App.vue
import Vuex from vuex
import store from ./store
Vue.config.productionTip false
Vue.use(Vuex)
new Vue({render: h h(App),store,
}).$mount(#app)4.在组件中使用
例 1.创建store/index.js
//引入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
})2.main.js
import Vue from vue
import App from ./App.vue
import Vuex from vuex
import store from ./store
Vue.config.productionTip false
Vue.use(Vuex)
new Vue({render: h h(App),store,
}).$mount(#app)3.Count.vue
templatediv//获取store/index.js中state中的全局属性sumh1当前求和为{{$store.state.sum}}/h1//获取store/index.js中getters中的全局计算属性属性bigSumh2结果乘以十后{{$store.getters.bigSum}}/h2select v-model.numbernoption value11/optionoption value22/optionoption value33/option/selectbutton clickincrement/buttonbutton clickincrementOdd当前求和为奇数再加/button/div
/templatescriptexport default {name:aCount,data() {return {n:1, //用户选择的数字}},methods: {increment(){//调用mutations中的方法this.$store.commit(ADD,this.n)},incrementOdd(){//调用action中的方法this.$store.dispatch(addOdd,this.n)}},}
/script4.app.vue
templatediv classcontainerCount//div
/templatescriptimport Count from ./components/Countexport default {name:App,components:{Count}}
/script将vuex中的属性和方法放到组件中去
mapState和mapGetters就是将全局属性和全局计算属性变成自己组件的data 用法
computed: {//借助mapState生成计算属性sum、school、subject对象写法...mapState({sum:sum,school:school,subject:subject}),//借助mapState生成计算属性sum、school、subject数组写法...mapState([sum,school,subject]),//借助mapGetters生成计算属性bigSum对象写法...mapGetters({bigSum:bigSum}),//借助mapGetters生成计算属性bigSum数组写法...mapGetters([bigSum])
},mapActions与mapMutations就是将全局方法变成自己组件的methods
methods:{//靠mapActions生成incrementOdd、incrementWait对象形式...mapActions({incrementOdd:jiaOdd,incrementWait:jiaWait})//靠mapActions生成incrementOdd、incrementWait数组形式...mapActions([jiaOdd,jiaWait])//靠mapActions生成increment、decrement对象形式...mapMutations({increment:JIA,decrement:JIAN}),//靠mapMutations生成JIA、JIAN对象形式...mapMutations([JIA,JIAN]),
}例
templatedivh1当前求和为{{sum}}/h1h3当前求和的10倍为{{bigSum}}/h3h3我是{{name}}我在{{school}}学习/h3select v-model.numbernoption value11/optionoption value22/optionoption value33/option/selectbutton clickincrement(n)/buttonbutton clickdecrement(n)-/buttonbutton clickincrementOdd(n)当前求和为奇数再加/buttonbutton clickincrementWait(n)等一等再加/button/div
/templatescriptimport {mapState,mapGetters,mapMutations,mapActions} from vuexexport default {name:aCount,data() {return {n:1, //用户选择的数字}},methods: {// 借助mapActions生成increment、decrement对象形式...mapMutations({increment:ADD,decrement:SUBTRACT}),// 借助mapActions生成incrementOdd、incrementWait对象形式...mapActions({incrementOdd:addOdd,incrementWait:addWait})},computed:{ // 借助mapState生成计算属性数组写法// ...mapState([sum,school,name]),// 借助mapState生成计算属性对象写法...mapState({sum:sum,school:school,name:name}),...mapGetters([bigSum])}}
/script模块化命名空间(就是多个组件共享在vuex中定义的属性和方法)
在store创建两个组件的js和index.js
1.count.js
export default{namespaced:true,//开启命名空间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:{ADD(state,value){state.sum value},SUBTRACT(state,value){state.sum - value}},state:{sum:0, //当前的和name:JOJO,school:尚硅谷,},getters:{bigSum(state){return state.sum * 10}}
}
2.person.js
import axios from axios
import { nanoid } from nanoidexport default{namespaced:true,//开启命名空间actions:{addPersonWang(context,value){if(value.name.indexOf(王) 0){context.commit(ADD_PERSON,value)}else{alert(添加的人必须姓王)}},addPersonServer(context){axios.get(http://api.uixsj.cn/hitokoto/get?typesocial).then(response {context.commit(ADD_PERSON,{id:nanoid(),name:response.data})},error {alert(error.message)})}},mutations:{ADD_PERSON(state,value){console.log(mutations中的ADD_PERSON被调用了)state.personList.unshift(value)}},state:{personList:[{id:001,name:JOJO}]},getters:{firstPersonName(state){return state.personList[0].name}}
}
1.index.js将countAbout和personAbout暴露
//引入Vue核心库
import Vue from vue
//引入Vuex
import Vuex from vuex
//引入count
import countOptions from ./count
//引入person
import personOptions from ./person
//应用Vuex插件
Vue.use(Vuex)//创建并暴露store
export default new Vuex.Store({modules:{countAbout:countOptions,personAbout:personOptions,}
})创建两个组件
1.创建Count.vue
templatedivh1当前求和为{{sum}}/h1h3当前求和的10倍为{{bigSum}}/h3h3我是{{name}}我在{{school}}学习/h3h3 stylecolor:redPerson组件的总人数是{{personList.length}}/h3select v-model.numbernoption value11/optionoption value22/optionoption value33/option/selectbutton clickincrement(n)/buttonbutton clickdecrement(n)-/buttonbutton clickincrementOdd(n)当前求和为奇数再加/buttonbutton clickincrementWait(n)等一等再加/button/div
/templatescriptimport {mapState,mapGetters,mapMutations,mapActions} from vuexexport default {name:aCount,data() {return {n:1, //用户选择的数字}},methods: {...mapMutations(countAbout,{increment:ADD,decrement:SUBTRACT}),...mapActions(countAbout,{incrementOdd:addOdd,incrementWait:addWait})},computed:{...mapState(countAbout,[sum,school,name]),...mapGetters(countAbout,[bigSum]),...mapState(personAbout,[personList])}}
/scriptPerson.vue
templatedivh1人员列表/h1h3 stylecolor:redCount组件求和为{{sum}}/h3h3列表中第一个人的名字是{{firstPersonName}}/h3input typetext placeholder请输入名字 v-modelnamebutton clickadd添加/buttonbutton clickaddWang添加一个姓王的人/buttonbutton clickaddPerson随机添加一个人/buttonulli v-forp in personList :keyp.id{{p.name}}/li/ul/div
/templatescriptimport {nanoid} from nanoidexport default {name:aPerson,data() {return {name:}},computed:{personList(){return this.$store.state.personAbout.personList},sum(){return this.$store.state.countAbout.sum},firstPersonName(){return this.$store.getters[personAbout/firstPersonName]}},methods: {add(){const personObj {id:nanoid(),name:this.name}this.$store.commit(personAbout/ADD_PERSON,personObj)this.name },addWang(){const personObj {id:nanoid(),name:this.name}this.$store.dispatch(personAbout/addPersonWang,personObj)this.name },addPerson(){this.$store.dispatch(personAbout/addPersonServer)}},}
/scriptmain.js和app.vue
main.js
import Vue from vue
import App from ./App.vue
import Vuex from vuex
import store from ./storeVue.config.productionTip false
Vue.use(Vuex)new Vue({render: h h(App),store,
}).$mount(#app)app.vue
templatediv classcontainerCount/hrPerson//div
/templatescriptimport Count from ./components/Countimport Person from ./components/Personexport default {name:App,components:{Count,Person}}
/script路由Vue Router
注意to“xxx” 如果只有路径不用家 “ ” 如果有参数 必须家 : , :to“xxx”
整个应用只有一个完整的页面点击页面中的导航链接不会刷新页面只会做页面的局部更新数据需要通过ajax请求获取 路由组件通常存放在pages文件夹一般组件通常存放在components文件夹
通过切换“隐藏”了的路由组件默认是被销毁掉的需要的时候再去挂载 每个组件都有自己的 r o u t e 属性里面存储着自己的路由信息整个应用只有一个 r o u t e r 可以通过组件的 route属性里面存储着自己的路由信息 整个应用只有一个router可以通过组件的 route属性里面存储着自己的路由信息整个应用只有一个router可以通过组件的router属性获取到
简单使用案例
1.下载vue-routernpm i vue-router 2.创建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}]
})2.main.js
import Vue from vue
import App from ./App.vue
import VueRouter from vue-router
import router from ./routerVue.config.productionTip false
Vue.use(VueRouter)new Vue({el:#app,render: h h(App),router
})3.app.vue
templatedivdiv!-- Vue中借助router-link标签实现路由的切换 --router-link to/aboutAbout/router-linkrouter-link to/homeHome/router-link/divdiv!-- 指定组件的呈现位置 --router-view/router-view/div/div
/templatescriptexport default {name:App,}
/script4.pages/Home.vue
templateh2我是Home组件的内容/h2
/templatescriptexport default {name:Home}
/script
5.pages/About.vue
templateh2我是About组件的内容/h2
/templatescriptexport default {name:About}
/script多级路由
在简单案例的基础上创建两个.vue: /pages/News.vue和/pages/Message.vue
News.vue
templatedivnews/div
/templatescriptexport default {name:aNews}
/scriptMessage.vue
templatedivmessage/div
/templatescriptexport default {name:a-message}
/script路由query传参
使用步骤 1.传递参数
!-- 跳转并携带query参数to的字符串写法 --
router-link :to/home/message/detail?id666title你好跳转/router-link!-- 跳转并携带query参数to的对象写法 --
router-link :to{path:/home/message/detail,query:{id:666,title:你好}
}跳转/router-link2.接收参数
$route.query.id
$route.query.title例 1.router/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from vue-router;
//引入组件
import Home from ../pages/Home
import About from ../pages/About
import News from ../pages/News
import Message from ../pages/Message
import Detail from ../pages/Detail
//创建并暴露一个路由器
export default new VueRouter({routes:[{path:/about,component:About},{path:/home,component:Home,children:[{path:news,component:News},{path:message,component:Message,children:[{path:detail,component:Detail}]}]}]
})2.Message.vue
templatedivdiv v-form in messageList :keym.id!-- 跳转路由并携带query参数to的字符串写法 --!-- router-link :to/home/message/detail?id${m.id}title${m.title}{{m.title}}/router-linknbsp;nbsp; --!-- 跳转路由并携带query参数to的对象写法 --router-link :to{path:/home/message/detail,query:{id:m.id,title:m.title}}{{m.title}}/router-link/divhr/divrouter-view/router-view/div/div
/templatescriptexport default {name:aNews,data(){return{messageList:[{id:001,title:消息001},{id:002,title:消息002},{id:003,title:消息003}]}}}
/script3.Detail.vue
templateulli消息编号{{$route.query.id}}/lili消息标题{{$route.query.title}}/li/ul
/templatescriptexport default {name:aDetail}
/script命名路由
简化路由跳转路径 router/index.js
{path:/demo,component:Demo,children:[{path:test,component:Test,children:[{name:hello //给路由命名path:welcome,component:Hello,}]}]
}Message.vue
!--简化前需要写完整的路径 --
router-link to/demo/test/welcome跳转/router-link!--简化后直接通过名字跳转 --
router-link :to{name:hello}跳转/router-link!--简化写法配合传递参数 --
router-link :to{name:hello,query:{id:666,title:你好}}
跳转/router-link路由params传参
特别注意路由携带params参数时若使用to的对象写法则不能使用path配置项必须使用name配置
1.router/index.js
{path:/home,component:Home,children:[{path:news,component:News},{component:Message,children:[{name:xiangqing,path:detail/:id/:title, //使用占位符声明接收params参数component:Detail}]}]
}2.传递参数
!-- 跳转并携带params参数to的字符串写法 --
router-link :to/home/message/detail/666/你好跳转/router-link!-- 跳转并携带params参数to的对象写法 --
router-link :to{name:xiangqing,params:{id:666,title:你好}}
跳转/router-link3.接收参数
$route.params.id
$route.params.title路由中使用props传递和接收参数
使用props传递和接收参数是要在使用params传递参数的基础上在router/index.js中添加处理内容后在路由组件中使用props:[‘aaa’,‘bbb’]接收参数
{name:xiangqing,path:detail/:id/:title,component:Detail,//第一种写法props值为对象该对象中所有的key-value的组合最终都会通过props传给Detail组件// props:{a:900}//第二种写法props值为布尔值布尔值为true则把路由收到的所有params参数通过props传给Detail组件// props:true//第三种写法props值为函数该函数返回的对象中每一组key-value都会通过props传给Detail组件props(route){return {id:route.query.id,title:route.query.title}}
}使浏览器没有路由点击的历史记录
作用控制路由跳转时操作浏览器历史记录的模式 浏览器的历史记录有两种写入方式push和replace其中push是追加历史记录replace是替换当前记录。路由跳转时候默认为push方式 开启replace模式
router-link replace ...News/router-link编程式路由导航
不借助实现路由跳转让路由跳转更加灵活
//一般在方法中使用点击事件触发
this.$router.push({name:xiangqing,params:{id:xxx,title:xxx}
})this.$router.replace({name:xiangqing,params:{id:xxx,title:xxx}
})
this.$router.forward() //前进
this.$router.back() //后退
this.$router.go() //可前进也可后退
缓存路由组件
让不展示的路由组件保持挂载不被销毁
//缓存一个路由组件
keep-alive includeNews //include中写想要缓存的组件名不写表示全部缓存router-view/router-view
/keep-alive//缓存多个路由组件
keep-alive :include[News,Message] router-view/router-view
/keep-alive
路由组件触发和失活的两个钩子
activated和deactivated是路由组件所独有的两个钩子用于捕获路由组件的激活状态 具体使用 activated路由组件被激活时触发 deactivated路由组件失活时触发
1.activated和deactivated是配合keep-alive一起使用的 2.没有keep-alive的时候是不会被触发的 3.存在keep-alive的时候可以将activated当作created进行使用 4.deactivated是组件销毁的时候触发此时的destory是不执行的
例
About.vue
templateh2我是About/h2
/templatescriptexport default {name:aAbout}/scriptHome.vue
templatedivh2Home组件内容/h2/div
/templatescriptexport default {name:aHome,activated(){console.log(Home组件被激活了)},deactivated(){console.log(Home组件失活了)}}
/scriptrouter/index.js
//该文件专门用于创建整个应用的路由器
import VueRouter from vue-router;
//引入组件
import Home from ../pages/Home
import About from ../pages/About
//创建并暴露一个路由器
export default new VueRouter({routes:[{path:/about,component:About},{path:/home,component:Home}]
})app.vue
templatedivdiv!-- Vue中借助router-link标签实现路由的切换 --router-link to/aboutAbout/router-linkrouter-link to/homeHome/router-link/divdivkeep-alive//注意在这里使用keep-alive!-- 指定组件的呈现位置 --router-view/router-view/keep-alive/div/div
/templatescriptexport default {name:App,component:{}}
/script路由守卫
全局路由守卫
//该文件专门用于创建整个应用的路由器
import VueRouter from vue-router;
//引入组件
import Home from ../pages/Home
import About from ../pages/About//创建一个路由器
const router new VueRouter({routes:[{name:guanyu,path:/about,component:About,meta:{title:关于,requireAuth: true}},{name:zhuye,path:/home,component:Home,meta:{title:主页,requireAuth: true},}]
})//全局前置路由守卫————初始化的时候、每次路由切换之前被调用
router.beforeEach((to,from,next) {console.log(前)if(to.meta.requireAuth){if(localStorage.getItem(aaa) bbb){next();}else{console.log(不允许通过);}}else{console.log(不需要验证直接放行)}
})
//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from){console.log(后,to,from)document.title to.meta.title || 硅谷系统
})//导出路由器
export default router
独享路由守卫
就是针对某一个组件进行拦截拦截方法写在router的内部
//该文件专门用于创建整个应用的路由器
import VueRouter from vue-router;
//引入组件
import Home from ../pages/Home
import About from ../pages/About
import Message from ../pages/Message
//创建一个路由器
const router new VueRouter({routes:[{name:guanyv,path:/about,component:About,meta:{title:关于}},{name:zhuye,path:/home,component:Home,meta:{title:主页},children:[{name:xinwen,path:message,component:Message,meta:{title:新闻},//独享守卫特定路由切换之后被调用beforeEnter(to,from,next){console.log(独享路由守卫,to,from)if(localStorage.getItem(aaa) bbb){next()}else{alert(暂无权限查看)}}}]}]
})//全局后置路由守卫————初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from){console.log(后置路由守卫,to,from)document.title to.meta.title || 硅谷系统
})//导出路由器
export default router组件内路由守卫
templateh2我是About组件的内容/h2
/templatescriptexport default {name:aAbout,//通过路由规则离开该组件时被调用beforeRouteEnter (to, from, next) {console.log(About--beforeRouteEnter,to,from)if(localStorage.getItem(aaa)bbb){next()}else{alert(无权限查看)}},//通过路由规则离开该组件时被调用beforeRouteLeave (to, from, next) {console.log(About--beforeRouteLeave,to,from)next()}}
/script路由器的两种工作模式
对于一个url来说什么是hash值—— #及其后面的内容就是hash值 hash值不会包含在 HTTP 请求中即hash值不会带给服务器 hash模式 地址中永远带着#号不美观 若以后将地址通过第三方手机app分享若app校验严格则地址会被标记为不合法 兼容性较好 history模式 地址干净美观 兼容性和hash模式相比略差
Vue UI组件库
1.element-ui 使用步骤