一篇文档带你过一遍vue所有的基础知识点

37 阅读16分钟

Vue以项目开发为标准所有的基础知识点。


npm 查看源


   源表示npm 插件的集合,就是一个全是插件的数据库
   
   npm get registry  // 查看源
   npm config set registry  // 设置源
   
   淘宝源 npm config set registry https://registry.npm.taobao.org
   官方源 npm config set registry https://registry.npmjs.org
   

环境配置

1.脚手架可以采取覆盖安装

2.脚手架版本升级即可创建vue3的工程

脚手架安装 与卸载

	//卸载3.0之前的版本
	npm uninstall -g vue-cli
	yarn global remove vue-cli
        
	//卸载3.0之后的版本(可以统一使用此指令卸载)
	npm uninstall -g @vue/cli
	yarn global remove @vue/cli

vue2安装最新版本

	npm install -g @vue/cli
        
	或者
        
	yarn global add @vue/cli

查看所有版本

	//查询3.0之前的版本
	npm view vue-cli versions --json
        
	//查询3.0之后的版本
	npm view @vue/cli versions --json

安装指定版本

	//安装2.9.6版本
	npm install -g vue-cli@2.9.6
	yarn global add vue-cli@2.9.6
        
	//安装3.0.3版本
	npm install -g @vue/cli@3.0.3
	yarn global add @vue/cli@3.0.3
        
	//安装4.0.5版本
	npm install -g @vue/cli@4.0.5
	yarn global add @vue/cli@4.0.5

查看当前版本号和帮助信息

	vue -V 或 vue --version
	vue -h 或 vue --help

卸载失败

	npm config ls -l

删除 npmrc文件

	where vue

删除 回显的文件

	vue 
	vue.cmd

卸载失败参考文档

使用vite

创建工程

  npm init vite-app  projectName

cd projectName

   cd projectName
   npm install
  
   启动 npm run dev
      

起步

  • 这里直接以项目为主

  • 安装脚手架以后

  • 使用Vue命令创建项目

    vue create projectname(名字需要小写)

  • 通过空格和enter键选择配置

 1.Press <space> to select

 2. <a> to toggle all

 3. <i> to invert selection

 4.Press <enter> to confirm(确认)
  • 多选选择
	Babel  ES6转ES5  

	router 

	vuex

	css Pre-processing CSS预解析器

	Linter / Formatter  语法检查
1.通过空格进行多选,通过回车键确认

2.不使用History模式 (Use history mode for router?)

3.仅作为报错(Esslint with Error preventing only)

4.保存时提交( Pick additional lint features)

5.单独的配置文件

(in dedicated config files)

(Where do you prefer placing config for

 Babel, ESLint, etc.? 

(Use arrow keys)

6.保留预设(Save this as a preset for future projects? (y/N))

然后就可以项目就可以安装成功!

配置成功以后

  • 创建基础的文件目录

删除不必要的文件(暂时没有)

  • 添加基础的文件

1.api

2.utils

3.asset->style->img

4.components

5.router

6.store

接下来才是真正的开始


混入知识

定义一个新文件为mixin.js

	// 此处是导出对象{
		// mixin:{}
	// }
	export const mixin ={
	    methods:{
	        Test(){
	          alert("测试");
	        }
	      }
	}


	import {mixin} from "../mixin/mixin.js"

	export default {
	  name: 'Home',
	  data(){
	    return{
	      name: "ktuor"
	    }
	  },
	  methods:{
	    Test(){
	      alert("测试");
	    }
	  },
	  mixins:[mixin],  // 此处引入的是导出的变量名
	}
   
   // 等价于

   import {fun} from "../mixin/mixin.js"

  export default {
  	name:"Home"
   	data(){
   		return {

   		}
   	},
	 methods:{
	  Test(){
	    alert("测试");
	     }
	 }
   }
   
   // 1. 关于data中数据以mixin中为主
   // 2. methods以组件中为主
   // 3. mounted 声明周期两者都要

插件

./plugin/plugin.js

 	// 定义
	// 包含install方法的一个对象,install的第一个参数是Vue,
	// 第二个以后的参数是插件使用者传递的数据。

	export default {
		install(Vue,options){
           console.info("666")
		} 

	}

	// 使用
	import plugin from "./plugin/plugin.js"
    vue.use(plugin,options)

vue的模板语法

  • 插值语法
	<!-- 数据源为data,形式为双大括号包含{{name}} -->
	此处会解释为纯文本

	<template>
	  <div class="home">
	      <div>{{name}}</div>
	  </div>
	</template>

	<script>
	export default {
	  name: 'Home',
	  components: {
	    HelloWorld
	  },
	  data(){
	    return{
	      name: "ktuor"
	    }
	  }
	}
	</script>

  • 指令

一些常见的指令

v-bind : v-on @ v-show v-if v-else v-for

	<!-- 1 -->
      <button @click="Test">
         測試點擊
      </button>
	<!-- 2 -->
      <button :value="1">
         測試點擊
      </button>
      <!-- 此处是将其用作属性,其值必须为表达式 -->

数据绑定

  • 单项数据绑定
  • 双向数据绑定
  • 本质 1.本质是vue内部管理程序捕获 value 2.可以自定value值
  • 注意点
    • 仅针对input表单元素
  • 区别 1.用户行为是否能够更新数据源
      <input type="text" :value="name">
      <input type="text" v-model="name">
      <!-- 使用v-model可以更改数据源 -->

软件架构模型

1.MVC 2.MVP 3.MVVm

	三者都是软件结构模型
	从时间上来说,MVC更早,MVP之后,MVVM以Vue为代表

	三者都是MV是相同的,一个是M(data model) 一个是(view model)
	不同在于C,P,VM

	1.数据通过controller交互,其中view和控制器一一对应
	2.数据和view通过P这个中间人进行交互,其中view可以被分离,但是更新渲染数据需要手动
	3.VM主动更新数据

	其中Controller 主要处理业务逻辑
	而Presenter 相当于一个中间
	VM则是M和V的统一,他等价于M和V。
	M和V是VM的代码体现,VM是M和V的内存表达

Object.defineProperty

可以追加属性并且实现get和set,操作获取修改另一个属性


 	 let number = 18
     let person={
      name:"ktuor",
      sex:"女",
     }
     Object.defineProperty(person,age,{

      value:18,
      enumberable:true,
      writable:true,
      configurable:true
    })
    
    Object.defineProperty(person,age,{

      get(){
        return number
      },
      set(value){
         number = value
      }
    })

vue数据代理

数据代理指的是可以通过一个对象操作另一个对象情况

	let obj ={ y:1 }
	let obj2 = { x:2 }
    
    // 实现了通过obj 操作obj2的需求

	Object.defineProperty(obj,'x'.{
		get(){
			return obj2.x
		}

		set(vaule)
		{
			obj2.x = value
		}
	})
    
    // 而在Vue中,可以通过模板中的数据去操作_data中的数据
    // 可以实现响应式
    // 三个对象分别为配置对象,vm中的数据,vm._data

vue中的数据监视原理


     let data={
      name:"ktuor",
      sex:"女",
     }
      
    const obs = new Observer(data)
    console.info(obs);

    let vm = {}
    vm._data = data = obs

    // 该方法是vue中的特殊方法
    // 会给每一个对象都添加上get和set属性
    // 从而实现响应式

    function Observer(obj) 
    {
       const keys = Object.keys(obj)
       keys.foreach((item,key)=>{
           Object.defineProperty(this,key,{
           	   get(){
           	   	 return obj[k]
           	   },
           	   set(value){
           	   	 obj[key] = value

           	   }
           })
       })
    }

    // new 到底做了什么?

    

Vue中对于数组的监视

	1.只能使用七个特殊的数组方法对数组进行修改
		1.1 否则数组无法侦测
	2.可以直接使用数组的过滤方法直接替换数组
	3.对于使用单个索引的数组,无法形成响应式和数据侦听

事件处理

  • 绑定方式

1.v-bind 2.@

  • 修饰符

.stop:阻止事件冒泡 .native:绑定原生事件 .once:事件只执行一次 .self :将事件绑定在自身身上,相当于阻止事件冒泡 .prevent:阻止默认事件 .caption:用于事件捕获 .once:只触发一次 .keyCode:监听特定键盘按下 .right:右键


	<button @click.left="shout(1)">ok</button>
	<button @click.right="shout(1)">ok</button>
	<button @click.middle="shout(1)">ok</button>

计算属性

对已有属性生成的新属性进行初始化

  • computed

  • 简写形式

	computed:{
		isName(){
			return this.isName
		}
	}

  • 完整形式
	comnputed:{
		isName:{
		get(){
           return this.isName
		},
		set(value){
		   return this.isName = value
		}
	}

监视属性

vue管理程序开放给开发者监听已有属性改变时需要做的事情

  • watch

  • 简写形式

	watch:{
      isName(){
      	//主要逻辑
      }
	}

  • 完整形式
	watch:{
	   isName:{
	   	 deep:true,
		 immediate:true,
		 handler(new,old){
           // 主要逻辑
		 }
	   }
	}

样式绑定

  • 类样式绑定
  • 内联样式绑定
  • 本质,vue内部是使用js添加 因此使用样式绑定会覆盖同一属性的类
  • 主要分类依据
    • 类名是否确定
    • 使用是否确定
    • 个数是否确定
  • 主要分类
	<div class="basic" :class="classArr">{{name}}</div> <br/><br/>
     
     1.字符形式 :class="className" 
     2.对象形式 :class="{
     	     类名:true,
     	     类名:false
     	}"
     3.数组形式["类名"]
     4.表达式 可以使用三木表达式,其结果依旧是类名(字符类型)

条件渲染

v-if 与 v-else属于一个组合 v-else-if

  • 可以是实现嵌套

  • 其值可以是为表达式

  • 表达式与语句的区分

    • 输出结果的是表达式
    • 而语句则是类型于
	if(){
		console.info("666");
	}

v-show 效果相同

  • 区别 display:none 与visibility:hidden的却别

其中v-if使用的是display:none 而v-show则是使用的visibility:hidden

  • 表达式必须要输出一个结果,否则不为表达式

列表渲染

v-for

  • 属性

    • item
    • index
    • key
  • key 的注意点

1.key是作为唯一标识符(身份证) 2.key的取值是item中,也就是数组的一项中的key

  • key的作用

与旧DOM进行比对,如果有更新,就使用新DOM进行替换

  • index

index 做为key 只能在一维数组中

过滤器

两个过滤器

  • 数组的过滤球
	 arr.filter((item,index)=> item[i]=== i)

	 <!-- 其中为条件 不改变原数组 返回新数组-->

  • VM的过滤器
		filter(){
			toForamt(value,str){
				return "str"
			}
		}

		// 使用

		在模板中使用对字符使用官道符号
		<!-- 管道符是将上一次结果作为参数传递到下一个函数 -->

内置指令

v-once v-text v-html v-cloak v-pre

自定义指令

指令定义在directives中

  • 使用其方法W为
	vue.directive('fbind',{
		bind(element,binding){
			element.value = binding.value
		},
		inserted(element,binding){
			element.focus()
		},
		update(element,binding){
			element.value = binding.value
		}
	})
  
     directives:{
     	big(eleement,binding)
     	{
     		 element.innerText = binding.value
     	},

     	fbind:{
				bind(element,binding){
						element.value = binding.value
					},
					//指令所在元素被插入页面时
				inserted(element,binding){
						element.focus()
					},
					//指令所在的模板被重新解析时
				update(element,binding){
						element.value = binding.value
				    }     		
     	}
     }


一般来说,可以使用vue的directive和组件内部的directives定义指令 他们不是触发制,而是监视制,观察制。通过监听其他元素从而执行操作

1.当指令和元素成功绑定时 2.当模板解析变化是 3.指令所在元素被插入页面时间

三个事件分别为bind,inserted,updated

生命周期

严格来说只有四个 分别为

1.created 2.destroyed 3.mounted 4.updated

加上他们的before,共有八个

其中updated 如果发现数据改变,就会立刻执行更新

1.beforeCreated 2.created

	此处主要是data数据的访问

	before时未开启数据代理,数据监测,因此此时数据无法访问
	created 时数据已经就绪,此时可访问methods

3.mounted 4.beforedMounted

	此处主要是DOM结构

	before是DOM结构未编译,不可使用
	mounted是DOM结果已经完成编译,可以使用事件等
   
	DOM结构渲染后一般开启定时器,发送网络请求,开启消息订阅,绑定自定义事件
	而Destory则相反

5.updated 6.beforeUpdated

	此处主要是数据与DOM的偏差
	before时数据是新的,DOM是旧的
	updated 数据是新的,DOM是新的,两者同步完成

7.beforeDestroyed 8.destroyed

	此处主要时定义的data,methods,事件是可用

	before时都可以使用
	destroyed彻底销毁

总的来说,数据,DOM,数据更新都需要时间。

因此让数据提前DOM次之显得十分有必要 而对数据的操作在created就可以开始 而对DOM的操作则要等到mounted完成

组件

主要是为了实现局部功能

组件有单文件组件和非单文件组件之分

  • 组件的基本流程

1.创建 2.注册 3.使用

单文件组件

    1.创建

	export default {
		name:"Home",
		data(){
			return{

			}
		}
	}

	2.在其他组件中引入

	import Home from "./Home.vue"

	data(){
		return{

		}
	},
	components:{
		Home
	}
	3. 在组件中使用

	<Home></Home>

非单文件组件


	let School = Vue.extend({
		  template:"<div>组件的创建</div>",
		  data(){
		  	return {

		  	}
		  },
		  name:"School"
		})

    1.注册在VM中就是全局组件
    2.注册在其他组件中就是局部组件

  • 组件的命名

1.school 2.School 3.MySchool 4.my-shcool

  • 组件的通信

1.父 => 子 props 2.子 => 父 自定义事件 3.兄弟与兄弟 全局事件总线 4.兄弟与兄弟 全局事件总线,Vuex 5.爷 => 孙 使用多次父=>子传递 6.孙 => 爷 使用多次自定义事件传递

全局事件总线

  • 事件上依赖于另一份的VM,总有两份VM
  • 本质上与Vuex一致
	//创建vm
	// 可以使用VM上的属性绑定
	new Vue({
		el:'#app',
		render: h => h(App),
		beforeCreate() {
			Vue.prototype.$bus = this //安装全局事件总线
		},
	})

新建一个文件globalBus.js 其中的代码如下


	import Vue from 'vue'
	export default new Vue()

ref属性

console.log(this.$refs.title) //真实DOM元素
console.log(this.$refs.btn) //真实DOM元素
console.log(this.$refs.sch) //School组件的实例对象(vc)

相当于id,作为唯一标识符

自定义事件

	组件可以使用自定义事件,通过使用组件时,把定义的组件传递过去
	定义时在,父组件中给子组件绑定事件,在子组件内部触发事件

	即 使用
	 this.$refs.student.$on('atguigu',this.getStudentName)

	 @atguigu = "atguigu" 
	 1.atguigu 写在methods里面

    由于是绑定在子组件上,子组件可以直接使用this触发

脚手架

脚手架的使用需要单独来讲

props配置

props配置组件中一般用于父子间通信

  • 传递方

将属性使用属性绑定在子组件上传递,

  • 接收方

此处即为子组件,也为接收方

共有三种形式

1.props:["name"] 简单接收 2.props:{ name:String, age:Number } // 限定数据类型

3.props:{ name:{ type:String, //name的类型是字符串 required:true, //name是必要的 }, age:{ type:Number, default:99 //默认值 }, sex:{ type:String, required:true } }


在路由中也有props传递行为

参数只能为params

  • 使用props传递参数
	// 1.具体形式在路由表定义
  	// 2.起点,当点击路由跳转时,
	// <!-- 参数被传递过来,而使用props接收 -->
	// <!-- 3.能被接收方直接使用(在data中) -->

	// 单条路由表中
	{
		props:ture
		props:{
			name:"ktuor"
		},
		props(route){
           return {
           	 id,
           	 title
           }
		}
	}

	// 接收方需要使用props接收

	props:["id","title"]

  • 插槽中的props传递 该功能知识为了解决数据源需要获取的情况 该方式与props在逻辑上是反向的 即传递方为子组件本身,数据源也在此处被获取 而接收方则是使用组件,通过slot-scope接收
	<!-- 传递方形式 -->

	<slot :games="games" msg="hello">我是默认的一些内容</slot>
      
    <!-- 数据源也在此处 -->

	<!-- 接收方形式 -->

	<template slot-scope="{games}">
				<h4 v-for="(g,index) in games" :key="index">{{g}}</h4>
	</template>

Style标签中的scoped

  • scoped

对CSS限制其作用域,使得其只作用于当前页面

  • lang="less"

此处指的是CSS解析器

使用less需要安装 less-loader@ 7.3.0

浏览器本地存储

浏览器本地存储,使用给定的接口可以 将我们的数据存放在本地磁盘中

一般使用localStorage.setItem(key,value)

存储

使用localStorage.getItem(key)

获取数据

过渡与动画

动画由关键帧定义

	@keyframes myAnimation{
		from {
			transform:translateX(-100%);
		}

		to{
			transform:translateX(0)
	}

过渡由transition定义


	transition:0.5s linear; 


共有以下关键点

  • 标签

  • 属性

1.name 2.appear 3.enter-active-class 4.leave-active-class

  • 类选择器

v-enter-active v-leave-active

name-enter-active name-leave-active

name-enter name-enter-to name-leave name-leave-to


name

使用transition和name属性相互配合 确定了在类中的位置,不然有多个类的话就无法确定

appear 是否在刷新时从起点运行过渡和动画

enter-active-class

1.对于v-enter-active
2.v-enter
3.v-enter-to
三者的封装

name-enter/leave-active

与name 相互配合使得一个确定的元素在active时选择何种行为

name-enter-0/to

与name 相互配合使得一个确定的元素在active时选择何种行为

v-enter/leave-active

不添加name

1.则无法确定一个元素 2.只能限定为一个元素

某个元素在active时选择何种行为

标签与属性与类选择器之间的关系

  • 标签和name属性是一体

  • 其中active是确定选择那种行为

  • name-enter/leave name-enter/leave-to

    • 则是描述选择行为中的两种状态

    • 中间的部分由计算机自动计算

  • 此外enter/leave-active-class 是封装了不同的行为

  • 而name属性则是两种行为的依赖

一个生动形象的例子

军训时,你因为偷偷撩妹被教官惩罚了。 你站在一个初始位置O,老师跟你说,当我说开始的时候 你可以选择蛙跳一百米运动和深蹲一百米运动,直到我说停的时候

这个时候,有个同学跟你一样,也被惩罚了。这个时候教官就分别给你们起了一个名字

当然,教官还提供了第三方扩展惩罚,就是一百米俯卧撑移动

代理服务器

跨域

插槽

共有三种类型插槽

1.默认插槽

2.具名插槽

3.作用域插槽

插槽的主要目的就是为了

同一组件需要差异化

标签

与一致是为了确定在页面中的位置

  • name

slot的名字,为插槽起名,避免多个插槽混乱

使用者的属性

  • slot

值为插槽的具体名字 一般是使用者的标签中包含 推荐在template中使用,会使得结构清晰分明

  • v-slot

仅限被template包裹的标签使用

用来指定插槽名称

形式为v-slot:center v-slot:slotname

  • scope

在作用域插槽中使用,一般为使用者的属性, 其值为包括传递的数据的对象

具体形式

1.调用者在组件内部添加上差异化view 2.使用template包裹,并为其指定插槽名称即可 3.形如:

        <!-- 默认插槽 -->
		<Category title="电影">
			<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
		</Category>	

		<!-- 组件内部 -->
		<slot msg="hello">我是默认的一些内容</slot>

		<!-- 具名插槽 he 被包裹template的插槽 -->
		<Category title="电影">
			<video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
			<template v-slot:footer>
				<div class="foot">
					<a href="http://www.atguigu.com">经典</a>
					<a href="http://www.atguigu.com">热门</a>
					<a href="http://www.atguigu.com">推荐</a>
				</div>
				<h4>欢迎前来观影</h4>
			</template>
		</Category>	

			<!-- 组件内部 -->
			<slot name="center"
			 msg="hello">我是默认的一些内容</slot>

			<!-- 作用域插槽 -->
			<template scope="{games}">
				<ol>
					<li style="color:red" v-for="(g,index) in games" :key="index">{{g}}</li>
				</ol>
			</template>

			<!-- 组件内部 -->
			<slot :games="games" msg="hello">我是默认的一些内容</slot>

路由

路由是一组对应关系,就好比一个物理接口对应一个网络接口 路由器则是管理这些对应关系的管理员

  • 安装

1.创建项目系统默认版本 2.选择默认版本时安装3.1.5版本

  • 环境配置
	// 从包中引入
	import VueRouter from "vue-router"
    import Vue from "vue"

    Vue.use(VueRouter);
    // 如果需要定义路由表

    const routes=[
    	{
    		path:"",
    		component:Home, //此处需要引入
    		component:()=>import "path" //推荐使用此方式
    	}
    ] 

    // 暴露变量

    const router = new VueRouter({
    	routes
    })
    export default router;


    // main.js 使用

    new Vue({
    	router
    }).$mount("#app")

    // 需要传入router才可生效
  • 主要配置项

routes

  • 主要内容

1.全局守卫 2.独享守卫 3.组件内守卫

全局守卫
  • 定义位置

在路由器上定义

	const router=new VueRouter({routes})

	router.beforeEach(function(to,from,next){})
	router.afterEach(function(to,from,next){})

独享守卫
  • 定义位置

在单个路由表上定位

	const router=new VueRouter({routes})

    router=[
    	{
    	  beforeEnter:function(to,from,next)
    	}
    ]

    children:[
			{
				name:'xinwen',
				path:'news',
				component:News,
				meta:{isAuth:true,title:'新闻'},
				beforeEnter: (to, from, next) => {
					console.log('独享路由守卫',to,from)
					if(to.meta.isAuth){ //判断是否需要鉴权
						if(localStorage.getItem('school')==='atuigu'){
							next()
						}else{
							alert('学校名不对,无权限查看!')
						}
					}else{
						next()
					}
				}
	}
 
组件内守卫
  • 定义位置

在组件内部的对象上定义

	export default{
		name:"Home",
		data(){
			return{

			}
		},
		beforeRouteEnter(){
              // 路由逻辑
			},
	}

路由本身的性质
  • 标签

路由本身有两个标签,分别为

router-link

该处为路由的入口,跳转的起点 其中to属性规定了路由跳转的路径

router-view

此标签为路由组件的放置位置,路由的出口 假若没有此标签,那么vue不知道将路由组件放置在页面的 哪一个位置

使用此标签便能确定路由组件的位置

关于多级路由

多级路由,当进入一级路由之后,就相当于进入一个作用域 在一个作用域中自然需要放置 router-view 和 router-view 标签

	routes:[

	         // 一级路由
			{
				path:'/about',
				component:About
			},
			{
				path:'/home',
				component:Home,
				// 二级路由
				children:[
					{
						path:'news',
						component:News,
					},
					{
						path:'message',
						component:Message,
					}
				]
			}
		]

  • to
	to有三种基本形式
	1.to="/home"  直接写路径
	2.to="/home/message/detail?id=666&tilte=你好啊"
	3.to="/home/message/detail/id/title"(需要在路由表配置)

	4.:to="{
		  path:"/detail"
		  query:{
		  	id,
		  	title
		  }
		}"

 	5.:to="{
		  name:"Home"
		  params:{
		  	id,
		  	title
		  }
		}"  // 对象形式,携带params参数,只能使用name形式
		    // 同时需要在路由表去除配置
		    // 因为parmas参数比较特殊,此处既然直接传递
		    // 便不用在路由中参数

    6.:to="`/home/message/detail?id=${m.id}&title=${m.title}`"

    7.命名形式

	 	7.1:to="{
			  name:"Home"
			  params:{
			  	id,
			  	title
			  }
			}"

		7.2 :to="{
			  name:"Home"
			  path:"/home/detail/message" // 
			  params:{
			  	id,
			  	title
			  }			
			}"
            
           // 此处仅说明path和name可以同时存在

	大家可以看到的是,对于第三种方式,vue如果解析还缺少一些东西

	如果不明确,便会有歧义,会有多种结果

	因此,必须要在route中配置

	即

	{
		path:"/home/message/detail/
		/:id/:title",
		component:()=>import "./Home.vue"
	}   

注意点

1.首先是路由表中配置,对于子路由可以去除"/",Vue默认解析

    path: '/',
    name: 'layout',
    component:()=>import("../views/layout/layout.vue"),
    children:[
        {
          path: '/index',
          name: 'index',
          component:()=>import("../views/index/index.vue"),
        },
       {
        path: '/article',
        name: 'artcile',
        component:()=>import("../views/article/article.vue"),
       }]

       // 不去除不影响
  1. 其次是对象形式下,携带params参数必须使用name形式, 因为如果使用path,等于重复配置
	:to={
		name:"Home",
		path:"/home/message/detial/id/title",
		params:{
			id,
			title
		}
	}
    
    // 此处还应该去除路由表配置
    // 这里params和path实际上会重复配置
    // 即path后的拼接参数和params

  1. 此外使用props传递时,props无法接收query参数
	{
		name:"home",
		path:"/home/message/detail",
		props:true
          // 此处接收方即要跳转的那个组件无法接收到query参数
          //  只能够接收params 参数
	} 

  • props形式

解决问题 当参数过多,会破坏代码的结构,是代码变得混乱 解决了参数过多的情况,参数接收时代码过于混乱

	{
		name:"home",
		path:"/home/message/detail",
		1.props:true
          // 此处接收方即要跳转的那个组件无法接收到query参数
          //  只能够接收params 参数
        props:{id:"666",title:"你好啊"}

        2.props(route){
           return {
           	 id,
           	 title
           }
        }

        或者

        3.props(route){
			return {
				id:route.query.id,
				title:route.query.title
			}
	    }
	}   


	// 接收方 

	export default {
		name:"Home",
		data(){
			return{

			}
		},
	  	props:["id","title"] 
	  	//这里接收以后就能够直接在模板中使用了

	  	computed(){
	  		id(){
	  			return this.query.id
	  		}
	  	}
	  	// 对于路由表中的props:true无法接收query的处理方式
	}



  • hash和history

形式

hash /home/message/detail/#/study

hisstory /home/message/detail/study

问题

用户刷新页面,hash不会向服务器发送请求,而history会主动向服务器发送请求

解决

1.无法阻止用户刷新 2.前端无法处理

后端配置history请求的页面

  • 编程式导航

push 和 replace

1.push会把路径压入栈结构 2.replace新生成的路径直接替换原有路径中的一条

理解

总共有两条路径 1.新生成的, 2.栈中原有的路径 push 会追加,栈中有两条路径 而replace 会替换,新直接换掉旧的,栈中只有一条路径

方法 1.push 2.replace 3.forward 4.back 5.go(step) step参数为数值,为步进值,一个步进值代表一条路径

  • 路由组件缓存

形式

路由切换时会直接销毁路由组件 解决路由切换时销毁路由组件,使得路由组件驻留在内存中

	<keep-alive>
	   <router-view></router-view>
	</keep-alive>

	// 其中属性为inlcude(p)

	// 参数p是组件名,可以是单个字符,可以是多个数组
	// "News" ["News","Home"]

路由组件生命周期钩子

activated deactivated

  1. 作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。
  2. 具体名字:
    1. activated路由组件被激活时触发。
    2. deactivated路由组件失活时触发。

Vuex

Vuex是集中式管理组件的一种功能 可以实现多组件通信,共享一份数据

  • 配置环境
	import Vuex from "vuex"
	import Vue from "vue"

    Vue.user(Vuex)
    
    const action={}
    const mutation={}
    const state={}

    export default new Vue.router({
    	action,
    	mutation,
    	state
    })

    //模块化

    import countOption from "./countOptions.js"
    export default new Vue.router({
       modules:{
       	countOptions
       }
    })
    
    // countOptions.js

    const countOption = {
     namespaced:true,//开启命名空间
     state:{x:1},
     mutations: { ... },
     actions: { ... },
     getters: {
       bigSum(state){
          return state.sum * 10
       }
     }
   }

   export default countOption

   // main.js 使用
   
   import store from "./store/store.js"

   new Vue({
   	 store
   })

  • 基本属性

1.action 处理业务逻辑,判断,循环等等 发送请求也在此处

2.mutation 此处执行逻辑运算

3.state 此处保留数据

4.getter 对于state中的数据进行二次处理

   const getters = {
   	bigSum(state){
   		return state.sum * 10
   	}
   }

  • 逻辑流程

1.模板环境

2.vm环境

3.action环境

4.mutation环境

模板中使用vm中的配置的数据,而实际数据源是在vm.(下划线)data中的

在vm环境中通过

this.$store.dispatch("actionFunctionName",p)

和定义在action中的函数对话

在action环境中通过

this.$store.commit("mutationFunctionName",p)

和定义在mutation中的函数对话

其中p = params 为传递的参数

  • 两个方法

dispatch()

commit()

  • 两个环境中定义的函数

   const action = {
   	   jian(context,value){
            // <!-- context 为 this.$store -->
   	   }
   }

   const mutation = {
   	   JIAN(state,value){
   	   	// state 为 this.$store.state
   	   }
   }

  • 四个函数自定义写法

模板用法

		<h1>当前求和为:{{$store.state.sum}}</h1>
        <h3>当前求和放大10倍为:{{$store.getters.bigSum}}</h3>

		<button @click="increment">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数再加</button>
		<button @click="incrementWait">等一等再加</button>

vm环境

	export default {
			name:'Count',
			data() {
				return {
					n:1, //用户选择的数字
				}
			},
			methods: {
				increment(){
					this.$store.commit('JIA',this.n)
				},
              
		    //  5 ****

				decrement(){
					this.$store.commit('JIAN',this.n)
				},
				incrementOdd(){
					this.$store.dispatch('jiaOdd',this.n)
				},
				incrementWait(){
					this.$store.dispatch('jiaWait',this.n)
				},

			// 5 ****

			}    
		}

store/index.js下的action和mutation

	const actions = {

		// 1 ****

		jiaOdd(context,value){
			console.log('actions中的jiaOdd被调用了')
			if(context.state.sum % 2){
				context.commit('JIA',value)
			}
		},
		jiaWait(context,value){
			console.log('actions中的jiaWait被调用了')
			setTimeout(()=>{
				context.commit('JIA',value)
			},500)
		}

		// 1 ****
	}
	//准备mutations——用于操作数据(state)
	const mutations = {

		// 2 ****

		JIA(state,value){
			console.log('mutations中的JIA被调用了')
			state.sum += value
		},
		JIAN(state,value){
			console.log('mutations中的JIAN被调用了')
			state.sum -= value
		}

		// 2 ****

	}
	//准备state——用于存储数据
	const state = {

		// 3 *****

		sum:0 //当前的和

		// 3*****
	}
    // getters在此处定义
	const getters={

		 // 4 *****

		 bigSum(state){
		 	return state.sum*10
		 }

		 // 4 *****

	}

可以看到 1,2,3,4,5 处结构相同,大量类似

mapState,matGetters,mapAction,mapMutation

  • 此处的目的就是为了简化1,2,3,4,5处的结构

map形式

    import {mapState,mapAction,mapMutation,mapGetters}

	methods:{

		...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
		...mapActions(["jiaOdd","jiaWait"])  

		// 对象形式
		...mapMutations({increment:'JIA',decrement:'JIAN'}),
		// 数组形式 这里简化默认key与value同名
		...mapMutations(["increment","decrement"]),


		}   

自定义形式action与mutaion

			 //程序员亲自写方法
         methods:{

  		    incrementOdd(){
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			},

			//程序员亲自写方法
			// 数组形式 这里简化默认key与value同名
			 increment(){
				this.$store.commit('JIA',this.n)
			},
		     decrement(){
				this.$store.commit('JIAN',this.n)
			},
         }

map形式state与Getters

		...mapState(["sum"])

		// 对象形式

		...mapState({sum:"sum"})

		 // 数组形式

		...mapGetters(["bigSum"])

		// 对象形式
		...mapGetters({bigSum:"sum"}) 

自定义形式state与Getters

		computed:{
			//靠程序员自己亲自去写计算属性
			/* sum(){
				return this.$store.state.sum
			},
			school(){
				return this.$store.state.school
			},
			subject(){
				return this.$store.state.subject
			}, */

			//借助mapState生成计算属性,从state中读取数据。(对象写法)
			// ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),

			//借助mapState生成计算属性,从state中读取数据。(数组写法)
			...mapState(['sum','school','subject']),

			/* ******************************************************************** */

			/* bigSum(){
				return this.$store.getters.bigSum
			}, */

			//借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
			// ...mapGetters({bigSum:'bigSum'})
			
			//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
			...mapGetters(['bigSum'])

  • 命名空间

为了实现模块化

特殊场景,有两个需求,一个是计算下单人数, 一个是订单结算

如果写在一个文件中会过于臃肿,不利于维护

定义

   // orderCount.js
   const orderCount = {
   	  actions:{},
   	  mutations:{}
   	  state:{}
   }
   export default orderCount

   // personCount.js
   const personCount = {
   	  namespaced:true,  //此处需开启此选项
   	  actions:{},
   	  mutations:{}
   	  state:{}
   }
   export default personCount

引入

	import orderCount from "./orderCount.js"
    import personCount from "./personCount.js"
    import Vue from "vue"
    import Vuex from "vuex"
   
    Vue.use(Vuex)

    export default Vue.Store({
    	modules:{
    		orderCount,
    		personCount
    	}
    })

使用(map)

假定这些方法都是orderCount内部的


	   methods:{

		...mapActions("orderCount",{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
		...mapActions("orderCount",["jiaOdd","jiaWait"])  

		// 对象形式
		...mapMutations("orderCount",{increment:'JIA',decrement:'JIAN'}),
		// 数组形式 这里简化默认key与value同名
		...mapMutations("orderCount",["increment","decrement"]),


		}   

使用(map)

假定这些方法都是orderCount内部的

	computed:{
		...mapState("orderCount",["sum"])

		// 对象形式

		...mapState("orderCount",{sum:"sum"})

		 // 数组形式

		...mapGetters("orderCount",["bigSum"])

		// 对象形式
		...mapGetters("orderCount",{bigSum:"sum"}) 

	}

自定义

假定这些方法都是orderCount内部的

	...mapState(['orderCount/sum','orderCount/school','orderCount/subject']),

vuex 使用

1.多模块需要开启namespaced

   const actions = {} 
   const state = {} 
   const mutations = {}
   const moduleName ={
   	namespaced:true
   }

   export default moduleName

   // import moduleName from "./module.name"
   // 其中自定义使用 / 区分  而map 则是独立参数 mapState(moduleName,{}/[])


2.state和gettters在computed中定义 3.actions和getters在metheods中定义 4.本质上通过调用dispatch和commit去修改state 5.自定义使用this.store.dispatch6.map是直接绑定7.上下文环境就是store.dispatch 6.map是直接绑定 7.上下文环境就是store

nextTick
	在下次DOM刷新之前调用
	访问方式 this.$nextTick(function(){})

  • 组件命名方式

官方推荐

1.school
2.MySchool
3.my-school
  • 赋值符号

变量是拷贝,对象是地址指向

  • VUE的软件架构模式

三种模式

1.MVVM 2.MVC 3.MVP

  • 自定义事件和绑定原生方法

在组件中自定义事件,一般绑定在组件实例对象上 @click.native native修饰符就可以

  • @keyup.ctrl.y

键盘事件,同时按下ctrl和y

  • 事件中值的获取

参数传递,传递event,默认传递event,默认传递event

  • 三个对象

    • options.data
    • vm.key
    • vm.(下划线datra)
  • delete方法

  • Object.keys(obj) Array.foreach()

  • 数据绑定简写形式

  • 数据绑定仅限表单元素

  • data的函数式和对象式

  • 为什么data不可以是箭头函数

箭头函数指向会改变

  • 闭包
	闭包指的是外部环境访问内部环境这一现象
	具体来说就是阻止了垃圾回收机制销毁内部变量,从而使得外部变量依旧可以访问内部变量

  • 原型链
	每一个对象都有一个内置对象,
	内置对象又有一个原型对象,直至到Object的原型对象为null

  • import 导入的数据量有几份?

一份

  • 如果我需要重新创建一份呢?

如何对一个组件进行拆分

脚手架

本质上就是webpack

代理服务器

代理服务器仅在vue开发环境中解决跨域问题

跨域问题

当前环境下请求了其他的环境

通用解决方案有 1.jsonp 2.cors 3.反向代理 4.代理服务器