总结内容基于2.x版本。
使用vue-cli生成命令 : vue create demo
mvvm , m model 数据模型, v ,view视图, vm vue 干了两件事 第一件 监听 dom , 第二件,把modal数据和view绑定起来
1, 选项 / 生命周期钩子
常用 钩子
beforeCreate:()=>{
console.log('beforeCrearte')
},
created:()=>{
console.log('created')
},
beforeMount:()=>{
console.log('beforeMount')
},
mounted:()=>{
console.log('mounted')
},
beforeUpdate:()=>{
console.log('beforeUpdate')
},
updated:()=>{
console.log('updated')
},
beforeDestroy:()=>{ // 销毁前
console.log('beforeDestroy')
},
destroyed:()=>{ // 销毁后
console.log('destroyed')
},
errorCaptured:(err, vm, info)=>{ // 销毁后
console.log(err, vm, info)
},
2,指令
mustache(胡子)语法 {{}}
可以配合过滤器使用 语法为 值 | 过滤方法 使用 filters 选项
filters:{
nameFix(name){
return name+'*'
}
},
{{item|nameFix}}
*************
v-once
{{msg}} // 只渲染一次
{{msg}} // 正常渲染
*******************
v-bind 用来绑定属性 简写为 :
1, 使用bind绑定 class , vue内部会对 已经声明的class和绑定的class做合并,
第一种是 对象语法 大括号里的key的键值对 的值 布尔值是否是true 来决定key是否应用的,
demo
第二张是数组语法,数组内item必须是字符串或者 data内的变量,也可以配合method,或者computed 来使用
methods :demo
computed: demo
2, 使用bind绑定 style, - 和小驼峰都支持 ,也可以配合method,或者computed 来使用
第一张是对象语法 : 和react 一样 ,
demo
第二种是数组语法 :
数据里有几个现成的样式, 然后会把这个样式进行合并
data:()=>{return {
style1:{fontSize:'50px'},
style2:{color:'lightblue'}
}},
demo
*********************
v-on 用来绑定事件 简写为 @
传递参数 :
1,不传参数, 会有默认事件参数传递
changeValue(e){
console.log(e)
},
2. 传如参数,直接传
changeValue(e){
console.log(e)
},
3, 希望参数和事件同事传递, 事件 通过$event传递 ,注意 事件要放到最后,否则值就丢了
changeValue(value,e){
console.log(value,e)
},
事件修饰符 :
阻止该事件冒泡
@click.stop
阻止默认行为 提交之类
@:submit.prevent="onSubmit"
阻止冒泡和捕获
@click.stop.prevent
监听键盘点击
1, 键代码
2, 键 名
原生组件监听修饰符 ,监听vue组件事件
@click.native
一次修饰符 .once
********************
v-if v-else v-else-if
组件 生成 还是不生成;
在某些特出场景中,输入框切换后, 值没有换掉,这是由于diff算法导致的, 解决办法加key ,key很重要
性能消耗比较大
********************
v-show 布尔值 display
组件隐藏还是显示
性能消耗比较小
********************
v-for
循环数组
movies:['八神','火神','雷神'],
-
{{item}}
v-for 要加key 优化性能,key的取值 ,最好不要取index, 而是取唯一的值, 否则 在做插入数组的时候性能算法消耗很大
循环对象
fighter:{
name:'八神',
age:'24',
skill:'八稚女'
}
-
{{value}}
********************
v-html v-text 两个都不用写文本, 直接绑定变量
html用来解析 html文本
text用来直接放文本
v-pre 原封不动的显示出来 不做任何解析
v-cloak 在加载成功以后再进行展示。避免那种 {{}} 直接出现 用在css里的
3, methods 和 computed
method 是方法名字 动词 , 在vue代码内调用 需要 (), 渲染 会每次都调用
computed 计算属性 是名次, 在vue代码内调用不需要 (),渲染 只会调用一次 有缓存
4, computed 的 setter和getter
computed:{
classes:{
get(){
return this.styleName
},
set(style){
this.styleName=style
},
}
},
get 默认返回, 一般用的都是get ,不用set
set方法调用
methods:{
changeValue(){
this.classes='activeClass2'
},
}
5, for of 和 reduce
/*
* for of
*/
let arr = [1,2,3];
// 可以直接拿到 item 展示
for(let item of arr){
console.log(item)
}
/*
* reduce
*/
let arr = [100,200,300];
// 传入一个函数, 函数的第一个参数是上一次计算的值, 第二个是循环item,
let result = arr.reduce((preValue,item)=>{
return preValue + item
})
console.log(result)
6, 哪些操作能够满足vue的及时响应 ,哪些不能呢 ?
可以:
一, 原生数组操作 都可以
二, 或者替换整个数组对象的地址
不可以:
修改数组已有的下标的值不可以引起响应
-
{{item}}
movies:['八神','火神','雷神'],
changeValue(){
this.movies[1] = 'k-dash'
},
7, v-model和几个form控件的配合使用
表单 v-model
这个 就等于 v-on和 v-bind 一起用
修饰符使用
.lazy 回车或者失去焦点时 才会发生改变 提高性能
.number 转为数字,配合input的type=number使用
.trim 去除首尾空格
*************************
select
单选
selectValue:'八神',
复选
选中了:
{{selectValues}}
movies:['八神','火神','雷神'],
selectValues:['八神'],
*************************
radio
选中了:
{{selectValues}}
movies:['八神','火神','雷神'],
selectValues:'八神',
**************************
checkbox checkbox的v-model交互做了修改为一个数组了
选中了:
{{selectValues}}
8, runtime-compiler 和 runtime-only 之间的区别
需要使用template模版的时候使用runtime-compiler
只使用.vue文件的时候 使用runtime-only
9 ,全局组件和 局部组件
// 全局注册 全局 的vue 上挂在了一个组件, 无论在什么全局的vue实例上直接使用
const comp = Vue.extend({ // extend 创建一个vue组件
template:`demo`,
data:{
a:222
}
})
Vue.component('cpn',comp);
// 语法糖
Vue.component('cpn',{ // extend 创建一个vue组件
template:`demo`,
data:{
a:222
}
});
// 局部注册components中注册 这种就只能在局部组件内使用了 , 一般用这个
const comp1 = Vue.extend({
template:`demo`,
data:{
a:222
}
})
const app1 = new Vue({
template:`demo`,
data:{
a:222
},
components:[comp1]
})
// 语法糖
const app1 = new Vue({
template:`demo`,
data:{
a:222
},
components:{
comp1 : {
template:`demo`,
data:{
a:222
}
}
}
})
10,template 模版分离写法 :
1, script 脚本段
Vue.component('cpn',{
template:'#cpn'
})
2, template标签
demp
Vue.component('cpn',{
template:'#cpn'
})
11 ,父子组件传参数 :
父传子
1, 父传子 通过props传递(bind 绑定 :,低版本中驼峰需要转成 - 连接形式), 通过props 约束
props 约束 有三种
1, 数组 props: ["hero","des"]
这种情况下直接声明注册
2, 对象约束具体属性
props: {
hero:Array,
des:String
}
3, 具体属性给予默认值 和ts 很像
props: {
des:{
type:String,
default:'aaa'
}
}
父组件
data:()=>{
return {
hero:['11','22','333'],
des:'demo'
}
},
子组件
- {{value}}
{{des}}
子传父
2, 子传父 通过$emit发射 父组件在子组件上绑定的事件
父组件在子组件上 是@ 绑定事件不是bind:绑定属性
父组件
methods:{
childClick(e){
console.log(e)
}
},
自组件
methods:{
btnClick(e){
this.$emit('cpmClick',e)
}
},
也可以顺便学习一下watch 函数
watch:{
nameDemo(newValue){
this.nameDemo= newValue;
this.$emit('cpmClick',newValue+'watchValue')
}
}
12, 父子访问组件方式
父访问子
1, $children 不常用 是个数组
2, $refs reference 引用的隐私 ----- 非常常用
子访问父亲
1, $parent 不常用
访问根节点
$root 不常用
13, 插槽 slot
插槽的作用就是把公共组件的公共部分又进行了抽象来使用 ,具体:
1, 简单使用 就是把标签内部的东西替换成 内容到预留位置
父组件
我是插槽
子组件
111
默认值的位置 输入默认值
2, 具名插槽 使用具体名字 来表示替换的某个部分 ,注意 不要直接加slot属性到组件上 ,要包裹span
父组件
我是插槽
具名插槽显示
子组件
111
默认值1
222
默认值2
3, slot 作用域
父组件替换子组件的在标签,但是利用子组件的默认数据重新写了内容
步骤一 slot 绑定数据 :data='nameDemo'
步骤二 使用template slot-scope="slot" 绑定作用域
父组件
- {{value}}-
子组件
14, router的基本使用
router/index.js
import VueRouter from 'vue-router';
import Vue from 'vue'
// 懒加载
//1, 会打出分包
//2. 以前的书写方式可能更为复杂
let home =()=>import ('../components/HelloWorld.vue');
let about =()=>import ('../components/About.vue');
// 1, 安装router
Vue.use(VueRouter);
// 创建router
const routes= [
{
path:'',
redirect:'/home'
},
{
path:'/home',
component: home
},
{
path:'/about',
component: about
}
]
const router = new VueRouter({
routes
});
// 导出 router
export default router
********************
// main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App),
}).$mount('#app')
********************
// App.vue
home
about
15, router-link router-view
home
about
1, router-link 链接
属性有这几种
tag 默认渲染 a , 但是可以改成其他标签元素
replace to的模式为pushstate,使用replace将改为replacestate,这样不会产生历史记录
activeClass 修改链接的选中默认样式
第一种方式
home
第二张方式
在router/index.js中 使用linkActiveClass 属性配置
const router = new VueRouter({
routes,
mode: 'history',
linkActiveClass:'red'
});
2, router-view显示视图 子路由也用这种方式显示 在组件内使用
3,方法跳转
this.$router.push('/home');
this.$router.repalce('/home');
16, 切换 hash 和history
/router/index.js 内修改mode属性即可
const router = new VueRouter({
routes,
mode: 'history',
});
17,嵌套路由
// router/index.js 注意子路由不写/
{
path:'/about',
component: about,
children:[
{
path:'message',
component: message
},
{
path:'detail',
component: detail
}
]
}
// About.vue
message
detail
18, router 和route的区别
router
放了全局方法和对象,包括路由配置元信息
*********
route
当前命中的路由属性
19,路由顶部传参
// 动态路由
// 1, restful风格path传参数
const routes= [
{
path:'',
redirect:'/home'
},
{
path:'/home',
component: home
},
{
path:'/about/:names',
component: about
}
]
// 传递
goAbout(){
this.$router.push('/about/xiaoming');
}
// 在about页面显示 /about/:names ,names 参数
computed:{
names(){
return this.$route.params.names
}
}
// 2 ,query 传参
写法一:使用点点击方法
goAbout(){
this.$router.push(
{
path:'/about',
query: {
names:'xiaoming',
age:12
}
}
);
}
写法二: 使用bind属性
about
// 拿到传递的query
computed:{
names(){
console.log(this.$route)
return this.$route.query.names
}
}
20,路由守卫
分为三种: before 函数里需要调用next方法, after 不需要
1,全局守卫
添加title
const routes= [
{
path:'',
redirect:'/home'
},
{
path:'/home',
component: home,
meta:{
title:'首页'
}
},
{
path:'/about',
component: about,
meta:{
title:'关于'
},
children:[
{
path:'',
redirect:'message'
},
{
path:'message',
component: message,
meta:{
title:'信息'
},
},
{
path:'detail',
component: detail,
meta:{
title:'详情'
},
}
]
}
]
router.beforeEach((to, from, next) => {
// meta 元数据
document.title = to.meta.title ? to.meta.title : to.matched[0].meta.title
next()
})
2,路由独享的守卫 写在route里
{
path:'/about',
component: about,
meta:{
title:'关于'
},
beforeEnter: (to, from, next) => {
document.title = to.meta.title ? to.meta.title : to.matched[0].meta.title
next()
},
}
3,组件内守卫 就像生命周期函数一样使用
beforeRouteEnter (to, from, next) {
console.log(this) // 访问不到 ,不能在这个地方才做this
next(vm => {
console.log(vm)
// 通过 `vm` 访问组件实例
})
},
beforeRouteUpdate (to, from, next) {
// just use `this`
this.name = to.params.name
next()
},
beforeRouteLeave (to, from, next) {
const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
if (answer) {
next()
} else {
next(false)
}
},
21,路由组件keep-alive,一般路由被卸载就会销毁 ,加上这个属性就不会被销毁 ,节省开销
exclude 这个属性是放开某个组件,逗号分割 不允许空格
22,vuex
1, 引入 创建实例
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex);
let store = new Vuex.Store({ // 注意Store 为大写
state:{ // 全局根状态管理器
count:1000
},
mutations:{ // 同步更新视图方法,可以直接更新但是为了工具插件能记录,所以要用mutations
add(state,{payload}){
//state.count++
state.count+=payload;
}
},
actions:{ // 异步发请求 仍需要mutations来提交
},
getters:{ // 类似computed
},
modules:{ // 更多模块的state
}
})
export default store;
2,引入 main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router/index'
import store from './store/global'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app')
3, state // 全局根状态管理器
在全局中使用
{{$store.state.count}}
4, mutations
使用commit 提交
mutations:{ // 同步更新视图方法,可以直接更新但是为了工具插件能记录,所以要用mutations
add(state,payload){
//state.count++
state.count+=payload;
}
},
methods:{
add(){
// 1,commit 方法来触发 方法名,
// this.$store.commit('add')
this.$store.commit('add',2) // 直接传入参数
// 2. commit 方法来类似react的diapatch触发对象写法
// this.$store.commit({
// type:'add',
// payload:2
// })
}
}
需要 mutations的方法名字和调用名字需要被抽离
export default {
'add':'add'
}
import mutationsType from './mutationsType'
[mutationsType.add](state,payload){
//state.count++
state.count+=payload;
}
5, actions
fetchSth(){
this.$store.dispatch('fetchSth')
}
fetchSth(context){ // context 就是当前store 上下文环境
setTimeout(() => {
// 通过commit提交让工具记录操作
context.commit(mutationsType.add,1);
}, 1000);
}
// 通过promise 来传递 回调参数
fetchSth(context){ // context 就是当前store 上下文环境
setTimeout(() => {
// 通过commit提交让工具记录操作
context.commit(mutationsType.add,1);
}, 2000);
return new Promise((resolve,reject)=>{
resolve('回调成功');
reject('')
})
}
this.$store.dispatch('fetchSth').then(res=>{
console.log(res)
})
6, getters
{{$store.getters.powerCount}}
getters:{ // 类似computed
powerCount(state){
return state.count*500;
}
},
入参数形式
getters:{ // 类似computed
powerCount(state){
return (params)=>{
return state.count+params
}
}
},
getters
{{$store.getters.powerCount(500)}}
7, modules
除了state 分 模块 的概念, 其他的都不区分模块的概念, 但是写的时候也写到一起
let moduleA = {
state:{
age:1111111
}
}
modules:{ // 更多模块的state
moduleA
}
{{$store.state.moduleA.age}}
8,store的 代码抽离
首先 modules 要全部抽出来,
其次 state和其他的属性如果太大可以抽离出来
23, promise
1 ,promise的函数是为了解决和回调地狱的问题
2, promise 接收两个函数作为参数 resolve ,reject
3, 这几个方法也可以 拆成 promise.resolve(),promise.reject() , 还有一个 promise.all 接收多个请求,都成功.then会得到一个数组 放两个请求的结果 ,用来处理并发请求,
4,.then 对应.resolve .catch 对应reject, 最后还有finally, 可以在。catch后继续.then
5,.then若需要继续.then下去回调 直接return res 就好 ;他是promise.resolve() 或者 new Promise(resolve)的简写
24,axios
1, 基本使用
import axios from 'axios';
axios({
url:'http://123.207.32.32:8000/home/multidata',
method:'get'
}).then(res=>{
console.log(res)
})
axios.get('http://123.207.32.32:8000/home/multidata').then(res=>{
console.log(res)
})
axios({
url:' http://123.207.32.32:8000/home/data',
params:{
type:'sell',
page:1
}
}).then(res=>{
console.log(res)
})
2, 并发请求
axios.all([
axios({
url:'http://123.207.32.32:8000/home/multidata',
method:'get'
}),
axios({
url:' http://123.207.32.32:8000/home/data',
params:{
type:'sell',
page:1
}
})]).then(res=>{
console.log(res)
})
3, 全局配置
axios.defaults.baseURL = 'http://123.207.32.32:8000';
axios.defaults.timeout = 5000
axios({
url:'/home/multidata',
method:'get'
}).then(res=>{
console.log(res)
})
4,实例封装
let request = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout: 5000
})
request({
url:'/home/multidata',
}).then(res=>{
console.log(res)
})
5, 封装请求
let request = (config)=>{
let instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout: 5000
})
// 自动返回一个promise
return instance(config);
}
request({
url:'/home/multidata',
}).then(res=>{
console.log(res)
})
6, 拦截器
let request = (config)=>{
let instance = axios.create({
baseURL:'http://123.207.32.32:8000',
timeout: 5000
})
//!!!!! 拦截器需要返回对应的响应体 config
// 配置发送成功和失败的拦截器
instance.interceptors.request.use(
config=>{
console.log('请求发送成功')
return config
},
err=>{
console.log('请求发送失败')
return err
}
)
// 配置响应成功和失败的拦截器
instance.interceptors.response.use(
config=>{
console.log('响应返回成功')
return config
},
err=>{
console.log('请响应返回失败')
return err
}
)
// 自动返回一个promise
return instance(config);
}