vue2学习笔记(高阶)

  •  Vue2数据双向绑定的原理

Vue2 数据双向绑定原理是通过数据劫持 + 发布者-订阅者模式 的方式来实现,首先是通过 ES5 提供的 Object.defineProperty() 方法来劫持(监听)各属性的 getter、setter,并在当监听的属性发生变动时通知订阅者,是否需要更新,若更新就会执行对应的更新函数。



  
  
  
  title


    
我是订阅者

 Object.getOwnPropertyDescriptor

对象原型的toString方法,以及数组的length属性都是不可枚举的。

对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

let obj = { foo: 123 };
//打印obj对象的foo属性的描述对象
Object.getOwnPropertyDescriptor(obj, 'foo')
//输出的对象:
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,  是否可以枚举
//    configurable: true
//  }

//Object的原型toString属性是不可枚举
Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
// false
//数组的长度length属性是不可枚举
Object.getOwnPropertyDescriptor([], 'length').enumerable
// false

$route 和 $router的区别

 $router 是VueRouter的实例,在script标签中想要导航到不同的URL,使用  $router.push方法

 $route为router跳转对象,里面可以获取当前路由的name,path,query,parmas等。

路由懒加载

方法一 resolve

import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)

export default new Router({
  routes: [
        {
          path: '/',
          name: 'HelloWorld',
          component: resolve => require(['@/components/HelloWorld'], resolve)
        }
  ]
}) 

方法二.import按需加载(官方写法)

const comA = () => import('url')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')

方法三 webpack提供的require.ensure()

{  
    path: '/home',   name: 'home',   
    component: r =>require.ensure([], () => r(require('@/components/home')), 'demo')
 }

.vue文件组成部分

1.

2.

3.

scoped作用与原理 

组件css作用域,避免子组件内部的css样式被父组件覆盖,起到隔离的作用。

组件通信有哪些方式

  1. 通过 props 传递
  2. 通过 $emit 触发自定义事件
  3. 使用 ref
  4. EventBus 
  5. $parent 或$root 
  6. attrs 与 listeners
  7. Provide 与 Inject
  8. Vuex

data属性是一个函数而不是一个对象原因 

每次调用产生一个新的地址空间防止数据被污染。

vue生命周期

  •  创建vue实例对象:  beforeCreate、 created
  •  挂载dom节点 : beforeMount、mounted
  •  数据更新 : beforeUpdate、updated
  • activated: 被 keep-alive 缓存的组件激活时调用

  • deactivated: 被 keep-alive 缓存的组件失活时调用

  •  组件销毁:  beforeDestroy、destroyed

父子组件生命周期构造函数执行顺序

加载渲染过程:
父 beforecreate,created,beforeMount 
子 beforecreate,created,beforeMount
子 mounted 
父 mounted 

子组件更新过程:
父 beforeUpdate
子 beforeUpdate
子 Updated
父 Updated

销毁过程:
父 beforeDestroy
子 beforeDestroy
子 destroyed
父 destroyed
如果常用的数据如果需要传递到子组件的话,最好在created 或者
beforemount,把数据请求回来,然后传递给子组件。

axios 

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,简单的理解就是ajax的封装。

post请求的时候参数通过data进行传递
其他请求的时候参数通过params进行传递

//get请求方式:
axios.get("api", {
	// 传递参数
	params: {
		key: value
	},
    // 设置请求头信息,可以传递空值
	headers: {
		key: value
	}
}).then((response) => {
	// 请求成功
	let res = response.data;
	console.log(res);
}).catch(error => {
	// 请求失败,
	console.log(error);
});


//post请求方式:
let data = {
	key: value
},
headers = {
	USERID: "",
	TOKEN: ""
};
// 若无headers信息时,可传空对象占用参数位置
axios.post("api", qs.stringify(data), {
	headers
}
}).then((response) => {
	// 请求成功
	let res = response.data;
	console.log(res);
}).catch((error) => {
	// 请求失败,
	console.log(error);
});


/**** 以下简单封装axios   request.js   ****/
// 导入axios
import axios from 'axios'
import { Message} from 'element-ui'
//1. 创建新的axios实例,
const service = axios.create({
  // 公共接口
  baseURL: process.env.BASE_API,
  // 超时时间 单位是ms
  timeout: 3 * 1000
})
// 2.请求拦截器
service.interceptors.request.use(config => {
   config.data = JSON.stringify(config.data); //数据转化,也可以使用qs转换
   config.headers = {
     'Content-Type':'application/json' //配置请求头
   }
   //如有需要:注意使用token的时候需要引入cookie方法或者用本地localStorage等方法,推荐js-cookie
   //const token = getCookie('名称');//这里取token之前,你肯定需要先拿到token,存一下
   //if(token){
      //config.params = {'token':token} //如果要求携带在参数中
      //config.headers.token= token; //如果要求携带在请求头中
    //}
  return config
}, error => {
  Promise.reject(error)
})

// 3.响应拦截器
service.interceptors.response.use(response => {
  //接收到响应数据并成功后的一些共有的处理,关闭loading等
  return response
}, error => {
   /***** 接收到异常响应的处理开始 *****/
  if (error && error.response) {
    // 1.公共错误处理
    // 2.根据响应码具体处理
    switch (error.response.status) {
      case 400:
        error.message = '错误请求'
        break;
      case 401:
        error.message = '未授权,请重新登录'
        break;
      case 403:
        error.message = '拒绝访问'
        break;
      case 404:
        error.message = '请求错误,未找到该资源'
        window.location.href = "/NotFound"
        break;
      case 405:
        error.message = '请求方法未允许'
        break;
      case 408:
        error.message = '请求超时'
        break;
      case 500:
        error.message = '服务器端出错'
        break;
      case 501:
        error.message = '网络未实现'
        break;
      case 502:
        error.message = '网络错误'
        break;
      case 503:
        error.message = '服务不可用'
        break;
      case 504:
        error.message = '网络超时'
        break;
      case 505:
        error.message = 'http版本不支持该请求'
        break;
      default:
        error.message = `连接错误${error.response.status}`
    }
  } else {
    // 超时处理
    if (JSON.stringify(error).includes('timeout')) {
      Message.error('服务器响应超时,请刷新当前页')
    }
    error.message = '连接服务器失败'
  }
  Message.error(error.message)
  return Promise.resolve(error.response)
})
var config = {
      method: type,   
      url
 }
 if(type==='post'){
      config.data = params;
 }else{
      config.params = params;
 }
const http =  function(type,url,params){
    return service(config) 
}
export default http;


//api.js
import http from './http'
/**
 *  @parms resquest 请求地址 例如:http://197.82.15.15:8088/request/...
 *  @param '/testIp'代表vue-cil中config,index.js中配置的代理
 */
let resquest = "/testIp/request/"

// get请求
export function getListAPI(params){
    return http('get',`${resquest}/getList.json`,params)
}
// post请求
export function postFormAPI(params){
    return  http('post',`${resquest}/postForm.json`,params)
}
// put 请求
export function putSomeAPI(params){
    return  http('put',`${resquest}/putSome.json`,params)
}
// delete 请求
export function deleteListAPI(params){
    return  http('delete',`${resquest}/deleteList.json`,params)
}


$nextTick的作用

Vue 是异步修改 DOM 的并且不鼓励开发者直接接触 DOM,但有时候业务需要必须对数据更改,刷新后的 DOM 做相应的处理,这时候就可以使用 Vue.nextTick(callback)来帮助我们处理更新后的dom数据。

通俗讲:是将回调函数延迟在下一次dom更新数据后调用,就是当数据更新了,在dom中更新渲染后,立即自动执行该函数。

tips:因为vue中更新dom是异步的,vue在监测到数据改变时并不会立即更新视图,而是开启一个队列,把同一个事件循环中观察到数据变化的watcher推送进这个对列,同时缓冲所有数据变化并去重,在下一个事件循环中,才执行去重后的任务; 如果同一个watcher 被多次触发,只会被推送到队列中一次(去重)。

使用this.$nextTick()之所以能获取到更新后的值,并不是改变了vue的渲染流程,而是改变了获取最新值的时间,并不是立即获取,而是等vue渲染完后再获取,即异步获取。

在vue中修改数据后,页面不会立刻更新,而是开启一个队列,并且缓存同一轮事件循环中的所有数据改变。在缓冲时会除去重复的操作,等到下一轮事件循环时,才开始更新。

Vue会将用户同步修改的多次数据缓存起来,等同步代码执行完,说明这一次的数据修改就结束了,然后才会去更新对应DOM。

实现组件缓存 

使用内置组件标签,作用是创造一个缓存的空间,用于保存组件状态或者避免重新全部渲染。

提供 include 和 exclude 属性,两者都支持字符串或正则表达式

1、

  
2、路由页面给需要的添加meta
APP.js页面

 
    
    
 
    
    

{
    path: '/',
    name: 'home',
    alias: '/home',
    components:{ home },
    meta:{
      keep:true //需要缓存
    }
  },
  

MVVM与MVC 

  • M:model模型---负责处理应用程序的数据和业务逻辑。
  • V:View视图---负责数据的展示,通常是用户界面(UI)。
  • C:controller控制器---接受用户的输入,处理请求,并更新模型和视图。它起到了一个中间人的作用,连接模型和视图。

  • M: model数据模型 (data里定义)      
  • V: view视图 (页面标签)
  • VM: ViewModel视图模型 (vue.js源码)----它负责处理视图的逻辑和状态,并通过数据绑定与视图进行交互。
常用修饰符

.prevent: 提交事件不再重载页面;

.stop: 阻止单击事件冒泡;

.once: 只执行一次这个事件

.enter:监听键盘enter键

Key值作用 

key值的作用是给元素添加一个唯一的标识符,提高vue渲染性能。当数据变化的时候,vue就会使用diff算法对比新旧虚拟Dom。 如果遇到相同的key值,则复用元素。如果遇到不同的key值则强制更新。

触发数组改变方法

  • push()

  • pop()

  • shift()

  • unshift()

  • splice()

  • sort()

  • reverse()

 不会触发数组改变方法

  • slice()

  • filter()

  • concat()

computed和watch 

(1)计算属性有缓存机制,侦听器没有

(2)计算属性不支持异步操作, 侦听器支持异步操作

(3)计算属性是一个额外新增的属性, 侦听器只能侦听data中的属性

(4)计算属性有返回值return,侦听器不需要return

(5)计算属性可以监听多个数据变化(计算属性内部用到的数据变化了,就会执行计算属性方法), 侦听器只能侦听一个数据的变化

//computed:
1. 支持缓存,只在依赖的数据发生变化时,才会重新计算,
否则当多次调用computed属性时,调用的其实是缓存;
2. 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3. 如果一个数据需要经过复杂计算就用 computed
4. 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,
是一个多对一或者一对一,(某个属性受多个属性影响)

//watch:
1. 不支持缓存,每调用一次就计算一次;
2. watch支持异步;
3. 如果一个数据需要被监听并且对数据做一些操作就用 watch
4. 当一个属性发生变化时,需要执行对应的操作;一对多(监听多个数据)

 vue中解决跨域做法

基于浏览器都遵循同源策略的原因,客户端非同源的服务器发起网络请求的时候就是跨域请求。

同源:协议,域名,端口都相同,反之非同源。

同源策略是一种安全策略,浏览器只允许本域名下的接口交互,非同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

解决方法一:跨域资源共享(CORS)

CORS是W3C规范,是一个让Web服务器支持跨域访问的标准。

CORS是一种安全机制,CORS技术通过HTTP头部来告知浏览器,可以让应用程序绕过同源策略。

只要在服务端设置Access-Control-Allow-Origin就可以实现跨域请求,若是cookie请求,前后端都需要设置。

由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,并非当前页的

cookie。

//node.js实现服务端示例
var http = require('http');
var server = http.createServer();
server.on('request', function(req, res) {
  res.writeHead(200, {
    // 后端允许发送Cookie
    'Access-Control-Allow-Credentials': 'true',  
    // 重点字段: 允许访问的域(协议+域名+端口),允许所有域用*通配符  
    'Access-Control-Allow-Origin': 'http://localhost:8080',    
    // HttpOnly:脚本无法读取cookie
    'Set-Cookie': 'key=1;Path=/;Domain=mfaying.github.io;HttpOnly'  
  });
  res.write(JSON.stringify(req.method));
  res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');

koa结合koa2-cors中间件实现

const Koa = require("koa");
const cors = require("koa2-cors");
const Router = require("koa-router");
const router = new Router({ prefix: "/api" });
const app = new Koa();
//koa请求跨域问题
app.use(
    cors({
        origin: function(ctx) {
            return ctx.request.headers.origin || ""; //这里是重点,动态获取地址 //*
        },
        credentials: true,
        exposeHeaders: ["WWW-Authenticate", "Server-Authorization"],
        allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"], //设置所允许的HTTP请求方法
        allowHeaders: ["Content-Type", "Authorization", "Accept"], //设置服务器支持的所有头信息字段
    })
);

// 引入路由中间件
app.use(router.routes()).use(router.allowedMethods());

app.listen(3000, () => {
    console.log("正在监听3000端口号!");
});

后端SpringBoot项目中的跨域配置

  /**
   * 跨域配置
   */
  @Bean
  public CorsFilter corsFilter() {
      CorsConfiguration config = new CorsConfiguration();
      config.setAllowCredentials(true);
      // 设置访问源地址
      config.addAllowedOriginPattern("*");
      // 设置访问源请求头
      config.addAllowedHeader("*");
      // 设置访问源请求方法
      config.addAllowedMethod("*");
      // 有效期 1800秒
      config.setMaxAge(1800L);
      // 添加映射路径,拦截一切请求
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      source.registerCorsConfiguration("/**", config);
      // 返回新的CorsFilter
      return new CorsFilter(source);
  }

CORS攻击原理:

通常情况下,浏览器限制从其他站点加载资源,同源策略将在控制网页上的用户密钥声明的范围内工作。但是,存在一种情况,是用于验证许可证的站点需要向其他站点发送请求。

这时,如果服务器接受CORS请求,将响应访问控制允许的请求,那么攻击者就可以利用这种情况从一个新的站点调用API来攻击目标站点。攻击者可以通过设置自己的Origin头绕过浏览器限制,并向目标站点发送请求。在目标站点上,访问控制允许攻击者站点的请求,从而允许他们获取敏感数据和执行操作。
防范CORS攻击:
1. 使用最小特权原则
-- 最小特权原则是指,将最小权限授予最小模块,只授予执行任务所需的最小权限。
2. 使用预请求
 -- 当浏览器准备发送不同于常规GET,POST和HEAD请求的请求类型时,它会发送预请求(Preflight Requests),即向目标站点发送OPTIONS请求,以获取服务器是否同意该请求的策略和方法。通过在浏览器正确配置OPTIONS请求,可以有效防止CORS攻击。在使用预请求时,应正确设置Access-Control-Request-Method、Access-Control-Request-Headers和Access-Control-Max-Age头部,这样可以确保请求的正常工作。  
3. 保持资源安全
-- 如果您不想允许任何来源访问您的API或资源,则要向API添加接口,以确保所有请求都是从预定义的来源发起的。
还可以通过以下几种方法来保护资源:
// 设置访问控制允许的来源 res.setHeader('Access-Control-Allow-Origin', 'http://www.example.com')

// 设置只能使用POST和GET方法 res.setHeader('Access-Control-Allow-Methods', 'GET, POST')

// 设置其他允许的HTTP头信息 res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, content-type')

虚拟 DOM 

  • 对真实DOM的抽象描述,以js对象(VNode节点)作为基础的树,用对象的属性来描述节点,就是一个js对象。
  • 虚拟DOM提高性能,不是说不操作DOM,而是减少操作DOM的次数,减少回流和重绘。虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
  • 虚拟Dom不比原生DOM快,没有任何框架可以比手动优化DOM更快,因为框架的DOM操作层需要应对任何上层可能产生的操作,所以他的实现需具有普适性。并且在内部,虚拟DOM还使用真实DOM来呈现页面或内容。

diff算法 

在进行新旧虚拟dom树的比较时,用到了diff算法。

1、diff 比较两个虚拟dom只会在同层级(①是否在同一层②是否有相同的父级)之间进行比较,不会跨层级进行比较。

2、diff是采用先序深度优先遍历得方式进行节点比较,即:该节点存在子节点,先比较子节点,然后再比较同级几点

兄弟组件通信--使用全局事件总线($EventBus)

// 在main.js中安装全局事件总线
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false
//创建事件总线,就相当于创建了一个新的vue实例
Vue.prototype.$EventBus = new Vue()
//创建vm
new Vue({
    el:'#app',
    render: h => h(App),
    beforeCreate() {
        //安装全局事件总线,
        //或 Vue.prototype.$bus = this 
    },
})

//接收数据的组件:
methods:{
 demo(data) {.....}
 },
 mounted() {
 this.$EventBus.$on('xxx', this.demo)// 或者是写箭头函数的回调
}

//提供数据的组件使用 :this.$bus.$emit('xxx', 数据)

何时使用beforeDestory

1、解绑自定义事件

2、清零定时器

3、解绑自定义dom事件,如window.scroll等

vue常见的性能优化

1、合理使用v-if和v-show

2、合理使用computed

3、使用v-for的时候动态添加key

4、自定义事件,dom事件在beforeDestory中及时销毁

5、合理使用异步组件

6、合理使用keep-alive

7、data层级不要太深

8、使用vue-loader在开发环境做编译模板

9、前端通用性能优化(图片懒加载/减少HTTP请求/合理设置HTTP缓存/资源合并与压缩/合并CSS

图片/将CSS放在header中/避免重复的资源请求/切分到多个域名)

10、使用ssr

代码层面:     

        1、v-if 和 v-show 区分使用场景

        2、computed 和 watch  区分使用场景

        3、v-for 遍历必须为 item 添加 key,且避免同时使用 v-if

        4、长列表性能优化

        5、事件的销毁 addEventlisenter 事件监听

        6、图片资源懒加载

        8、路由懒加载

        9、第三方插件的按需引入

        10、优化无限列表性能

        11、服务端渲染 SSR or 预渲染

        12、组件模块尽量细化,一个组件一个功能,减少耦合

        13、子组件样式尽量用scoped,防止污染父组件

        14、(!important )不使用或减少用

Webpack 层面的优化       

        1、Webpack 对图片进行压缩

        2、减少 ES6 转为 ES5 的冗余代码

        3、提取公共代码

        4、模板预编译

        5、提取组件的 CSS

        6、优化 SourceMap

        7、构建结果输出分析

        8、Vue 项目的编译优化

基础的 Web 技术的优化       

        1、开启 gzip 压缩

        2、浏览器缓存

        3、CDN 的使用

        4、使用 Chrome Performance 查找性能瓶颈

vuex状态管理库

vuex 是一个专门为 vue 构建的状态管理工具,主要是为了解决 多组件之间状态共享问题。强调的是集中式管理,(组件与组件之间的关系变成了组件与仓库之间的关系)。

state         是状态管理器的状态中心,里面是初始化的数据,不可以直接操作Store 中的数据。

mutation  同步操作,改变store的数据,变更Store 数据,
                 通过commit提交方法,this.$store.commit('xxx')。

action      异步操作,改变store的数据,  让motation中的方法能在异步操作中起作用   
                通过store.dispatch 来分发actions中通过commit提交mutations,
                进行修改数据。

getter      是状态管理器中的计算属性,主要用来过滤一些数据,可以在多组件之间复用。

module   将 store 分割成模块,每个模块都具有state,mutation、action、getter、
               甚至是嵌套子模块。
  •  State

提供唯一的公共数据源,所有共享的数据统一放到store的state进行储存,相似与data

//在标签中直接使用

{{$store.state.name}}

//定义后直接使用 this.$store.state.全局数据名称  //在组件中导入使用 import { mapState } from "vuex";

 

  •  Mutation 

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

vue2学习笔记(高阶)_第1张图片

//使用commit触发Mutation操作
methods:{
    //加法
    btn(){
        this.$store.commit("addcount",10)     //每次加十
    }
}

//使用辅助函数进行操作

vue2学习笔记(高阶)_第2张图片

  • Action ——进行异步操作

Action和Mutation相似,一般不用Mutation 异步操作,若要进行异步操作,使用Action。

定义:vue2学习笔记(高阶)_第3张图片

使用:一、this.$store.dispatch("asynAdd")

  • Getter

类似于vue中的computed,进行缓存,对于Store中的数据进行加工处理形成新的数据

  • Modules 

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

v-model 指令   //  双向绑定       

含以下三个修饰符:

.lazy 默认情况下,v-model同步输入框的值和数据。可以通过这个修饰符,转变为在change

事件再同步。

 .number 自动将用户的输入值转化为数值类型

 .trim 自动过滤用户输入的首尾空格

 vue.js两个核心是什么?

数据驱动和组件化

 路由钩子(路由守卫)

全局路由守卫

        router.beforeEach(to, from, next),全局前置守卫

        router.beforeResolve(to, from, next),全局的解析守卫

        router.afterEach(to, from ,next) 全局的后置守卫

组件内守卫    路由独享的守卫

        beforeRouteEnter

        beforeRouteUpdate

        beforeRouteLeave

路由独享守卫

        beforeEnter   组件内的守卫

从a页面进入b页面时触发的生命周期

1)beforeRouteLeave:路由组件的组件离开路由钩子,可取消路由离开;

2)beforeEach:路由全局前置守卫,可用于登录验证,全局路由loading等;

3)beforeRouteEnter:路由的组件进入路由前钩子;

4)beforeResolve:路由全局解析守卫;

5)afterEach:路由全局后置钩子;

6)beforeCreate:组件生命周期,不能访问this;

7)created:组件生命周期,可以访问this,不能访问dom;

8)beforeMount:组件生命周期;

9)deactivated:离开缓存组件a,或者触发a的beforeDestory和destoryed组件销毁钩子

10)mounted:访问/操作dom;

11)activated:进入缓存组件,进入a的嵌套子组件(如果有的话);

12)执行beforeRouteEnter回调函数next

vue-router 路由模式

1.hash路由 – 默认模式

工作原理:监听网页的hash值得变化===》onhashchange事件,获取location.hash

使用URL的hash来模拟一个完整的URL,于是URL改变时,页面不会重新加载,会给用户好像跳转了网页一样的感觉,但是实际上没有跳转,主要用在单页面应用(SPA)。

在地址栏会有一个#号,因为hash发生变化的url都会被浏览器记录下来,浏览器的前进后退都可以用了,同时点击后退时,页面字体颜色也会发生变化。
这样一来,尽管浏览器没有请求服务器,但是页面状态和url一一关联起来,
后来人们给它起了一个霸气的名字叫前端路由,成为了单页应用标配。
2.history路由-------有的back、forward、go 方法

history ——利用了HTML5 History Interface 中新增的pushState() 和replaceState() 方法。
提供了对历史记录进行修改的功能。它能让开发人员在不刷新网页的情况下改变站点的 URL

History 有 URL 重定向问题,需要在服务端去配置 url 重定向,否则会报 404 错误。

history模式下,**前端的url必须和实际向后端发起请求的url 一致**,
如 http://www.abc.com/book/id 。如果后端缺少对/book/id 的路由处理,将返回404错误。
3.Abstract

abstract 模式针对的是没有浏览器环境的情况,比如 Weex 客户端开发,内部是没有浏览器 API 的,那么 Vue-Router 自身会对环境做校验,强制切换到 abstract 模式,
如果默认在 Vue-Router 的配置项中不写 mode 的值,
在浏览器环境下会默认启用 Hash 模式,在移动客户端下使用 abstract 模式。
 

由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除 

对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 `Vue.set(object,key, value)`方法向嵌套对象`添加响应式属性`。

节点ref属性的作用 

获取dom元素 this.$refs.box

获取子组件中的data this.$refs.box.msg

调用子组件中的方法 this.$refs.box.open()

路由传参的方式 

query传参和params传参

区别:params传参,浏览器地址栏不显示参数,用query传参,浏览器地址栏显示参数,所以用params传值相对安全。

1)声明式导航

不带参跳转 对应的地址为/foo

url字符串拼接传参 对应的地址为/foo?id=123

query方式对象形式传参 对应的地址为/foo?id=123

params方式对象形式传参 对应地址为 /path/123 , 注意params和query一起使用params会失效,

params与name一起使用

2)编程式导航(路由实例对象router=new VueRouter())

字符串router.push('home')

对象router.push({ path: 'home' })

命名的路由 对应路径为/path/123

router.push({ name: 'user', params: { userId: '123' }})

带查询参数,变成 /register?plan=123

router.push({ path: 'register', query: { plan: '123' }})

接收参数

this.$route.params.id

this.$route.query.xxx

在路由对象内,通过props属性 开启传参功能
在组件对象内 通过props接收
原因: 为了降低路由和组件的耦合度。

在子路由对象中设置props
 {
  path:'/detial:id',
  name:'detail',
  components:{
    default:()=> import(/* webpackChunkName: "pro" */'@/views/detail/detail.vue')
  },
  props:{
    default:true
  }
 }

minix  混入

mixin提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。

当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。选项属性相同情况下,被混入对象的选项优先级最高。

 

 Vue Loader

Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件。



Vue Loader 还提供了很多酷炫的特性:

  • 允许为 Vue 组件的每个部分使用其它的 webpack loader,例如在