数据绑定
单向数据绑定
- v-bind:href = "xxx" 可简写为:href = "xxx"
- 数据只能从data流向视图
双向数据绑定
- v-mode:href = "xxx"
data的两种写法
对象式写法
- data:{name:'name'}
函数式写法
-data:function(){return}
//如果在组件中,必须使用函数式写法 因为如果写成对象的话,组件上的值可以被改变
计算属性
- data中的属性存在于vm._data中 而computed则是通过计算直接赋值给vm
- computed中的get中的this被vue改成了vm
- get调用的时机有两次:
1. 初始化的时候(也就是说如果一个页面中有多处用到计算属性时,在初始化时只会调用一次,之后的值都为缓存)
2. 依赖的属性更新时
- vm.计算属性会自动调用计算属性中的get方法 而不是计算属性.get
- set没必要写 //当计算属性被修改时才会被使用
- 简写: 如果不需要set方法 可简写成
//计算属性:function(){return xxx}
监视属性
两种写法
- watch:{ obj:{immediate:true, handler(newValue,oldValue){}}}
- vm.$watch('obj',{相同的写法}
各项属性
- immediate 初始化时让handler调用一下
- handler 当obj发生改变时会被调用
- deep:true时,会监视到多级结构中某个属性的变化
简写
- 只需要handler时,可使用简写方式,obj(newValue,oldValue){}
自定义指令
- directives:{
dir(element,binding){}
element指的是绑定的dom binding指的是vlue
}
notice: 当设置为函数时,会在以下两个时间点进行调用, 1. 指令与元素成功绑定时 2. 指令所在的模版被重新解析时
- 当设置为对象时
bind()//指令与元素成功绑定时
inserted()//指令所在元素被插入页面时
updated()//所在的模版被重新解析时
这些钩子函数都能收到element 和 binding元素 并且在这些方法中的this为window
组件
什么是组件
- 实现应用中局部功能代码和资源的集合
1. 解决了依赖关系混乱, 不好维护的问题
2. 解决了代码复用率不高的问题
- 局部注入组件
- Vue.extend({})
- components:{}
- 全局注入组件
- Vue.component('component',component)
- name: 可以指定组件在开发者工具中出现的名字
- 组件的嵌套
- 组件中的this指向vueComponent
- 组件是可复用的vue实例,所以接受与new Vue相同的选项,除了el这种根实例所特有的选项
- VueComponent.prototype._proto_ === Vue.prototype
ref
- 类似于id 可以通过this.$refs.xx 拿到
notice: 当获取组件的ref时得到的是vc
props
- 简单接受 props:{}
- 可以限制接受的数据类型
- e.g. props:{name:String}
- 也可以有更多属性限制
- e.g. props:{name:String required:true,default:10} //default 与 required一般不同时使用
- notice: 不要直接修改props传过来的数值,可以通过在data中定义一个变量来接受并且进行修改
mixins
- 将暴露出的变量先用import导入,然后再用mixins接收,
- 当mixins中的变量与原有变量冲突时,以原有变量为主
- 在main.js中引入 并用Vue.mixin() 即代表全局混入
插件
- Vue.use(plugin,optioanl(参数))
- 在插件中的行参是Vue
- 定义插件 对象.install =function(Vue, options){
此处可添加全局的东西
}
组件自定义事件
绑定及触发自定义事件
- 之前可通过父组件给自组件传递函数类型的props实现:子给父传递数据
- 父组件在子组件标签内添加 v-on:'自定义事件‘ = 'methods中的func',之后通过在子组件中的this(vc).$emit('自定义事件',optional(参数) )
1. 自定义事件 不需要子组件用props接受
2. 可通过给子组件绑定ref 然后通过this.$refs.xxx.$on('自定义事件',callback') 一般在mounted中绑定,而且$on can replace to $once代表只能使用一次 也可在@自定义事件后加上.once
解绑自定义事件
- this.$off() 可传数组,如果不传任何参数代表解绑所有的自定义事件 当组件销毁的时候,绑定的所有自定义事件都会被销毁,原生dom上的事件 会被保留
- 在自定义事件中 谁触发的自定义事件 this就为谁 在methods中的方法的this一直都为vm
- 在子组件上添加@click时 会被认为是自定义事件,需变成@click.native 才会被认为是点击事件
全局事件总线
- 能够实现任意组件间的通信
- 前置: $on $emit $off... 都是vc和vm的原型上的方法
- 实现步骤:
1. const Demo = Vue.extend({}) const d = new Demo() //不推荐
2. 在main.js中 beforeCreate方法中设置 Vue.prototype.$bus = this
3. 使用这种方法需要在beforeDestroy中进行解绑,要不就一直存在
pubsub-js
- publish&subscribe github上查看用法
$nextTick
- 里面的callback会在DOM节点更新完毕之后再执行
动画与过渡
- 待做 前置知识: CSS3 动画
配置代理
axios
- 如何解决跨域
1. cors 需要在后端加上响应头(negative:谁都能访问)
2. jsonp(script src)需要前后端配合 并且只能进行get请求 post等不能(用得少)
3. 配置一个代理服务器(常用):
- 白话来说就是设置一个同域的服务器接受前端的请求,atst 服务器与服务器之间的请求不受跨域限制
- 开启的方式
- nginx 反向代理服务器
- vue-cli
- 开启的配置 devServer.proxy 位于vue.config.js中
- 在proxy中设置联系的服务器地址
- negative: 1. 不能配置多个服务器地址 2. 如果所请求的资源在本地上有会优先寻找本地的资源
- 可以在proxy中声明多个数组解决如上缺点, 使用pathRewrite属性利用正则表达式替换
fetch (TODO)
vue-resource
- npm i vue-resource 再引入 Vue.use() 就可以使用 通过this.$http.methods使用
slot
- 声明在组件的页面结构当中,当在使用组件时在中间插入结构时,就会替代slot的位置(default)
- 具名插槽 name 在标签里是slot="name" 第二种写法是当v-slot = method(只在template里面有用)
- 作用域插槽 作用是将子组件的数据通过slot传递给父元素 父元素通过template 标签中的scope or slot-scope 进行接收 可传递多个元素
v-text diff with 插值语法: v-text会替换掉节点中的内容, 哪怕有html标签
Vuex
- 实现多组件共享数据
- 使用场景:1. 多个组件依赖于同一状态 2. 来自不同组件的行为需要依赖同一状态
- 步骤
在Action阶段, 可能会通过backend API获取到值,
在main.js中声明store
新建一个文件夹store创建一个index.js(一般都这样)
其中引入Vue & Vuex 同时Vue.use(Vuex)
- step
actions(dispatch触发) 中接受两个行参(context,value) context为上下文的意思 value代表接受的变量
mutations(commit触发) 中接受两个行参(state,value) 这个时候可以操作state
state中可以设置公共变量
getters
- 用于将state中的数据进行加工
- 接收的行参为state
- 与computed类似 依赖的数据变化了就会自动改变
mapState & matGetters
- mapState
- step
- import {mapState} from 'vuex'
- 在computed中...mapState({key:value})
- 如果同名, 可以将{key:value}替换成{['key']}
- mapGetters 同理
mapActions & mapMutations
- notice:
- diff with mapState: 方法需要传参
Vuex 模块化
- Purpose: 让代码更好维护, 让多种数据分类更加明确
notice:
声明时:
- 需要给每个模块加上namespaced: true
- 在store文件夹中声明不同功能的js index中import
使用时:
- 如使用mapxxx等,按照以下格式
- ...mapState('xxx',['xxx'])
- 如采用普通模式书写
需要按照 xxx/xxx 格式
路由
就是一种key-value的关系
原理 key: 就是路径 /class这种 value:就是所展示的组件
notice:如果在actions中对state进行操作,Devtool就监测不到了
SPA页面
- 整个页面只有一个完整的页面
- 点击导航链接不会刷新页面,只会做页面的局部更新
- 数据需要通过ajax请求获取
路由分类
- 后端路由
- value是function 用于处理客户端提交的请求
- process: 服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回响应的数据
- 前端路由
- value是component 用于展示页面内容
- 当路径改变时,对应的组件就会显示
路由基本使用
- router-link 实现路由的切换
- router-view 指定组件的呈现位置
- active-class 指定组件激活时候的样式名
- 几个注意点
- 不用的组件会被销毁
- 组件上的$router是一样的 $route是不一样的
多级路由
notice: 需要子路由中声明children添加path时需注意不要添加/ but在router-link中需声明完整路径
路由传参
- 两种写法
- 1. to加: 并且之后的值用模版字符串+${}来书写
- 2. :to={path:xxx, query:xxx}
- 接受query后 用$route.query.xxx来取值
命名路由
- 将name取在配置项中
- 作用: 简化path
但不是to="name"的写法
而是:to="{name:xxx}"
路由的params属性
- 配置路由的时候必须声明接受params属性 且需要使用占位符
e.g. path:'detail/:id/:count
- 传递的时候 to的字符串写法为 :to="home/id/count"
to的对象写法:
需注意不能与path同时使用
需与name同时使用
路由的props配置
声明在路由配置项中
- 1. 值为对象 所有key-value都会以props的形式传递给Detail组件
- 2. 值为Boolean,若为true,将会把所有接收到的params参数以props的形式传递给Detail组件
- 3. 值为函数 所有返回的值都会用props的形式传递,并且会接受$route为行参 这样可以获取到query上的值
路由的replace选项
开启方法有两种
- 1. 完整模式 :replace="true"
- 2. 简写模式 replace
作用: 有两种写入方式,分别为push和replace push是追加 也就是入栈 replace是替换该条记录
编程式路由导航
- 作用: 不借助routerlink实现路由跳转
- 借助的是$router 而不是$route
- attention: 重复点击可能会报错
keep-alive
- 让不展示的路由组件不被销毁,保持挂载
- keep-alive包裹router view 如不加includes 则所有组件都不会被销毁,如果要加的话需注意是组件名,可写成数组模式
两个路由的生命周期钩子
- activated
- deactivated
- 需要搭配keep-alive使用
路由守卫
- 全局路由守卫
- beforeEach 3 attribute to from next()
- afterEach 2 attribute to from
- 可以用来给每个路由页面添加title
- 路由独享守卫
- 只有beforeEnter
- 组件守卫
- beforeRouteEnter (to from enter)
- 通过路由规则,进入该组件时被调用
- beforeRouteLeave (to from enter)
- 通过路由规则,离开该组件时被调用
路由工作的两种模式
通过在router中添加mode来改变工作模式
- # hash工作模式
- 兼容性好
- #后面的都不会发送给后端
- history工作模式
- 部署时 容易出问题
- 需要后端配合
- nodejs中间件: connect-history-api-fallback
# 未完待续