记录vue的一些基本使用。
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ │── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
├── package-lock.json:包版本控制文件
单向数据绑定:
双向数据绑定:
data() {
return {
name:'张三同学'
};
},
1 M:模型(Model) :data中的数据
2. V:视图(View) :模板代码
3. VM:视图模型(ViewModel):Vue实例
观察发现:
1.data中所有的属性,最后都出现在了vm身上。
2.vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
事件的基本使用:
1.使用v-on:xxx 或 @xxx 绑定事件,其中xxx是事件名;
2.事件的回调需要配置在methods对象中,最终会在vm上;
3.methods中配置的函数,不要用箭头函数!否则this就不是vm了;
4.methods中配置的函数,都是被Vue所管理的函数,this的指向是vm 或组件
事件修饰符
1.prevent:阻止默认事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只触发一次(常用);
4.capture:使用事件的捕获模式;
5.self:只有event.target是当前操作的元素时才触发事件;
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
键盘事件
enter,delete ,esc,space,tab,up,down,left,right
姓:
名:
全名:{{fullName}}
//vue.js中的代码段
data() {
return {
firstName:'张',
lastName:'三',
};
},
computed:{
fullName(){
console.log('haha')
return this.firstName + '-' + this.lastName
}
}
姓:
名:
全名:{{fullName}}
//代码段
data() {
return {
firstName:'张',
lastName:'三',
fullName:'张+三'
};
},
watch:{
firstName(val){
setTimeout(()=>{
console.log(this)
this.fullName = val + '-' + this.lastName
},1000);
},
lastName(val){
this.fullName = this.firstName + '-' + val
}
}
字符串写法,绑定class样式1{{name1}}
数组写法{{name2}}
对象写法,可以动态地决定样式的显示和隐藏{{name3}}
style对象写法{{name4}}
style数组写法{{name5}}
//js部分
data() {
return {
name1:'张三',
name2:'李四',
name3:'王五',
name4:'赵六',
name5:'田七',
// 字符串写法
style1:'class1',
// 数组写法
arrayStyle:['array1','array2','array3'],
// 对象写法
OjbectClass:{
obj1:true,
obj2:false
},
// 对象objStyle写法 骆峰式写法
styleObj:{
fontSize:'16px',
color:'blue',
border:'1px solid pink'
},
//对象数据写法
styleArray:[
{
fontSize:'16px',
color:'red',
},
{
border:'1px solid red'
}
]
};
},
//style部分
v-if,v-show,v-for,v-model,filter
v-text,v-html,v-cloak,v-once,v-pre
1. 被用来给元素或子组件注册引用信息(id的替代者)
2. 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
3. 使用方式:
1. 打标识:```
1. 功能:让组件接收外部传过来的数据(常用于父组件向子组件传值)
2. 传递数据:```
3. 接收数据:
1. 第一种方式(只接收):```props:['name'] ```
2. 第二种方式(限制类型):```props:{name:String}```
3. 第三种方式(限制类型、限制必要性、指定默认值):
```js
props:{
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}
使用方式一:父组件向子组件传值
父组件
子组件
- {{ option.label }}
使用方式二:兄弟组件之间传值
父组件
这是父组件
子组件child1
兄弟组件一
{{childOne}}
兄弟组件之间通信
子组件child2
兄弟组件二{{childTwo}}
当点击组件child1中的事件之间,组件1和组件2中的数据同步更新为100
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
1. 功能:可以把多个组件共用的配置提取成一个混入对象
2. 使用方式:
第一步定义混合:
```
{
data(){....},
methods:{....}
....
}
```
第二步使用混入:
全局混入:```Vue.mixin(xxx)```
局部混入:```mixins:['xxx'] ```
就是把所有公用的部分单独抽取出来,如data、components、created、methods 、computed、watch等。假如有这样的一个需求,两个组件里面分别有姓名和年纪信息,并且点击姓名弹出姓名,正常情况下需要写两个事件分别弹出姓名。但是我们如果使用混入就要简单的多了。
第一步先在src下新建一个mixin.js文件,在这个文件下面写入代码
export const mixi={
methods:{
btn(){
alert(this.name)
}
}
}
接着在两个需要用到的组件中分别引入并使用
组件1代码
姓名是{{name}}
组件2代码
姓名是{{name}}
包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
假如有两个组件里面有各自需要实现的功能,一个功能能对字符串进行截取,另一个是点击按钮弹出各自的提示,正常情况下是需要写两个事件和两个字符分割的操作,如果使用插件就简单得多。
1,使用的第一步在src目录下新建一个plugins.js文件,接着在js文件下添加对应的代码
export default{
install(Vue){
//这里对字符串进行截取
Vue.filter('strSlice',function(value){
return value.slice(0,4)
});
//添加一个原型方法
Vue.prototype.fun=()=>{
alert("vue.js")
}
//...还可以添加其它的
}
}
2,全局引用
import Vue from 'vue'
import App from './App'
import router from './router'
//引入store
import store from './store/index'
import plugins from './plugins'//引入插件
Vue.use(plugins)//使用插件
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store:store,
components: { App },
template: ' '
})
3,在对应的组件中使用
组件1
{{name|strSlice}}
组件2
{{name|strSlice}}
首先在父组件在添加自定义事件,这里的父组件是App.vue
//这里的btn1需要和methods中的btn1保持一至
methods: {
btn1(){
alert("自定义事件")
}
}
调用自定义事件,这里是子组件
{{name}}
//这里点击按钮会看到对应的提示
首先在组件顶部添加一个div,div里面有names,names在data中,并且值为空
{{names}}
data() {
return {
names:''
};
},
mounted () {
console.log(this)
},
methods: {
//这里给btn1添加了一个参数
btn1(val){
this.names=val
}
}
在子组件中的处理
{{name}}
注意点
1. 一种组件间通信的方式,适用于:子组件 ===> 父组件
2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件事件的回调在A中
3. 绑定自定义事件:
1. 第一种方式,在父组件中:```
2. 第二种方式通过ref,在父组件中:
```js
......
mounted(){
this.$refs.xxx.$on('customBtn',this.test)
}
```
3. 若想让自定义事件只能触发一次,可以使用```once```修饰符,或```$once```方法。
4. 触发自定义事件:```this.$emit('atguigu',数据)```
5. 解绑自定义事件this.$off('customBtn') //解绑一个自定义事件
// this.$off(['customBtn','customBtn1']) //解绑多个自定义事件
// this.$off() //解绑所有的自定义事件
6. 组件上也可以绑定原生DOM事件,需要使用```native```修饰符。
7. 注意:通过```this.$refs.xxx.$on(' ',回调)```绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
首先在main.js中添加全局事件事件总线
new Vue({
el: '#app',
router,
store:store,
components: { App },
template: ' ',
//添加全局事件总线
beforeCreate(){
Vue.prototype.$bus=this
}
})
接下来创建两个组件,现在需要做的是需要把组件A中的数据传递到组件B中
A组件
{{name}}
B组件
总结
1,一种组件间通信的方式,适用于任意组件间通信。
2,A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
1,安装npm i pubsub-js(消息订阅与发布的组件不止这一种,也有其它的插件,区别就是语法上面)
2 ,引入 import pubsub from 'pubsub-js'(在需要用到的组件中使用)
现在有两个组件,想将组件A中的数据传到组件B
组件A
{{name}}
组件B 一共有3种写法
{{name}}
总结:
1,消息订阅与发布只发生在需要用到的组件之间;
2,那个组件想要接收数据,就在那个组件订阅消息,回调留在当前组件,发布由指定的组件进行。
1. 作用:在下一次 DOM 更新结束后执行其指定的回调。
2. 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
注意:支持不同数据一次性传递到子组件的方法
父组件中有这样的数据
//把data中的color,cat,dog传递到子组件,只需要用一个titlelist,但需要用到data中各自的名称
data() {
return {
names:'',
//要把这三个数据传递到子组件
color:['黄','白','黑'],
cat:['狸花猫','波斯猫','宠物猫'],
dog:['小狗','大狗','黑狗']
};
},
子组件只需要一次遍历即可
{{title}}
- {{item}}
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件。
分类:默认插槽、具名插槽、作用域插槽
1,默认插槽
父组件
- {{item}}
data() {
return {
names:'',
//要把这三个数据传递到子组件
color:['黄','白','黑'],
cat:['狸花猫','波斯猫','宠物猫'],
dog:['小狗','大狗','黑狗']
};
},
子组件
{{title}}
默认插槽,没有内容的时候显示
2,具名插槽 作用就是把相对的内容填充到相应的插槽中,一个萝卜一个坑,对应的名字填充到对的slot中,默认插槽无法做到。
具体使用
- {{item}}
- 张三
- 李四
- 五五
哈哈
哈哈
对应数据
data() {
return {
names:'',
//要把这三个数据传递到子组件
color:['黄','白','黑'],
cat:['狸花猫','波斯猫','宠物猫'],
dog:['小狗','大狗','黑狗']
};
}
子组件
{{title}}
默认插槽,没有内容的时候显示
默认插槽,没有内容的时候显示
3,作用域插槽
重点:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。
具体使用父组件
- {{item}}
- {{item}}
{{item}}
data() {
return {
names:''
};
},
子组件
{{title}}
默认插槽,没有内容的时候显示
1,概念
在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
2,什么时候使用?
多个组件需要共享数据时
1,第一步先安装vuex,目前是以vuex3的版本
2,在src下新建一个store文件,然后在这个文件下面新建一个store.js文件
3,在main.js中进行引入
首先实现组件A和组件B中的数据同时变化,在store.js文件中添加这样的代码
//引入vue和vuex
import Vue from "vue";
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//基本数据用来存储变更
state:{
//初始数据为0
num:0
},
//用于修改state中的数据,属于同步操作
mutations:{
//这里的名称addNum是要在A组件中调用的点击的
addNum(state){
state.num++
}
},
//用来处理异步操作
actions:{
},
//用于对store中的数据进行加工处理
getters:{
}
})
组件A
{{$store.state.num}}
组件B
{{this.$store.state.num}}
点击组件A中的按钮,组件A和组件B中的数字会同时发生变化
传递参数的写法store.js中的写法不变,在原来的mutations里的addNum里加了一个参数
mutations:{
//传递一个参数为n1
addNum(state,n1){
state.num+=n1
}
},
组件A里面的写法,组件B还是和原来的一样保持不变,点击按钮可以看到每点一次,数字加2
{{$store.state.num}}
异步操作,点击异步按钮之后等3秒会执行减减操作,组件B还是和之前一样
//引入vue和vuex
import Vue from "vue";
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//基本数据用来存储变更
state:{
num:0
},
//用于修改state中的数据,属于同步操作
mutations:{
//传递一个参数为n1
addNum(state,n1){
state.num+=n1
},
addjs(state){
state.num--
}
},
//用来处理异步操作
actions:{
//这个wati需要和点击事件中的一样
wait(count){
setTimeout(()=>{
console.log('这是个异步')
//这里需要用到commit并且要和mutations里面的addjs一至
count.commit('addjs')
},3000)
}
},
//用于对store中的数据进行加工处理
getters:{
}
})
组件A
{{$store.state.num}}
处理数据
//引入vue和vuex
import Vue from "vue";
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//基本数据用来存储变更
state:{
num:0
},
//用于修改state中的数据,属于同步操作
mutations:{
//传递一个参数为n1
addNum(state,n1){
state.num+=n1
},
addjs(state){
state.num--
}
},
//用来处理异步操作
actions:{
//这个wati需要和点击事件中的一样
wait(count){
setTimeout(()=>{
console.log('这是个异步')
//这里需要用到commit并且要和mutations里面的addjs一至
count.commit('addjs')
},3000)
}
},
//用于对store中的数据进行加工处理
getters:{
setNum(state){
return '当前num是'+state.num
}
}
})
组件A
{{$store.state.num}}
{{setNum}}
组件B
{{this.$store.state.num}}
{{$store.getters.setNum}}
使用vuex存储数据
//子组件1
兄弟组件一
vuex存取数据
//vuex
export default{
namespaced: true,
state:{
name:""
},
mutations:{
//这里的名称SaveVuex一样
SaveVuex(state,newValue){
state.name=newValue
console.log(newValue)
}
},
getters:{
}
}
//子组件2
兄弟组件二
{{"哈哈"+name}}
传入一个数组
//父组件
{{"父组件"+name}}
//最终的结果就是点击组件1里面的事件,组件2和父组件同步更改
map4个方法
1,mapState方法:用于帮助我们映射```state```中的数据为计算属性
2,mapGetters方法:用于帮助我们映射```getters```中的数据为计算属性
3,mapActions方法: 用于帮助我们生成与```actions```对话的方法,即:包含```$store.dispatch(xxx)```的函数
4,mapMutations方法用于帮助我们生成与```mutations```对话的方法,即:包含```$store.commit(xxx)```的函数
1. 理解: 一个路由(route)就是一组映射关系(key - value),多个路由需要路由器(router)进行管理。
2. 前端路由:key是路径,value是组件。
1. 安装vue-router,命令:npm i vue-router
2. 应用插件:Vue.use(VueRouter)
3. 编写router配置项:
//引入路由
import Vue from 'vue'
import Router from 'vue-router'
import rout1 from '../pages/rout1.vue'
import rout2 from '../pages/rout2.vue'
//使用
Vue.use(Router)
//配置项
const router=new Router({
routes: [
{
path:'/rout1',
component:rout1
},
{
path:'/rout2',
component:rout2
}
]
})
export default router
接下来在pages里面创建两个组件,并完成一个query传参,params的用法和query相同
特别注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!
组件一{{$route.query.id}}
组件一{{$route.query.name}}
组件二{{$route.query.id}}
组件二{{$route.query.title}}
接着在app里面通过query向这两个组件分别传递参数
rout1
rout2
当然还可以传递其它的数据
rout1
rout2
路由props的配置,让路由组件更方便地接收到参数
//引入路由
import Vue from 'vue'
import Router from 'vue-router'
import rout1 from '../pages/rout1.vue'
import rout2 from '../pages/rout2.vue'
//使用
Vue.use(Router)
//配置项
const router=new Router({
routes: [
{
path:'/rout1',
component:rout1
},
{
path:'/rout2',
component:rout2,
//props配置
props($route){
return{
id:$route.query.id,
name:$route.query.name
}
}
}
]
})
export default router
通过props接收
组件二{{id}}
组件二{{name}}
1. 作用:控制路由跳转时操作浏览器历史记录的模式
2. 浏览器的历史记录有两种写入方式:分别为push和replace,push是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
3. 如何开启replace模式:
编程式路由导航
1. 作用:不借助
2. 具体编码:
```js
//$router的两个API
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() //可前进也可后退
缓存路由组件
1. 作用:让不展示的路由组件保持挂载,不被销毁。
2. 具体编码:
两个新的生命周期钩子
1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
2. 具体名字:
1. activated路由组件被激活时触发。
2. deactivated路由组件失活时触发。
路由守卫
1. 作用:对路由进行权限控制
2. 分类:全局守卫、独享守卫、组件内守卫
路由器的两种工作模式
1. 对于一个url来说,什么是hash值?—— #及其后面的内容就是hash值。
2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
3. hash模式:
1. 地址中永远带着#号,不美观 。
2. 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
3. 兼容性较好。
4. history模式:
1. 地址干净,美观 。
2. 兼容性和hash模式相比略差。
3. 应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
父组件调用子组件中的方法
方法一过ref直接调用子组件的方法
//父组件中
//子组件中
我是子组件
方法二通过组件的$emit、$on方法
//父组件中
//子组件中
我是子组件
子组件通过$emit方法调用父组件函数
父组件
这是父组件
子组件
兄弟组件一
调用子组件方法
父组件调用子组件中的函数
父组件
父组件调用子组件
//这里需要ref
子组件
兄弟组件一
兄弟组件之间方法的调用 (通过子组件1调用子组件2里面的方法)
//兄弟组件1
兄弟组件一
调用兄弟组件里面的事件
//父组件
//兄弟组件2
兄弟组件二
未完待续.....