定制小程序开发费用Vue2 概述

什么是Vue

 

定制小程序开发费用引用官网的一段话:Vue (读音 /vjuː/,类似于 view) 定制小程序开发费用是一套用于构建用户界面的定制小程序开发费用渐进式框架。定制小程序开发费用与其它大型框架不同的是,Vue 定制小程序开发费用被设计为可以自底向上逐层应用。Vue 定制小程序开发费用的核心库只关注视图层,定制小程序开发费用不仅易于上手,定制小程序开发费用还便于与第三方库或既定制小程序开发费用有项目整合。另一方面,当与定制小程序开发费用现代化的工具链以及各种支持类库定制小程序开发费用结合使用时,Vue 定制小程序开发费用也完全能够为复杂的单定制小程序开发费用页应用提供驱动。

  • VUE是一款由定制小程序开发费用数据驱动视图定制小程序开发费用的前端框架,它基于MVVM(Model View View Model)模式,定制小程序开发费用定制小程序开发费用实现数据与视图的双向绑定。
  • MVVM:Model定制小程序开发费用表示数据模型,View表示视图,定制小程序开发费用指由数据驱动视图,定制小程序开发费用当数据发生改变时,定制小程序开发费用视图会自动改变,定制小程序开发费用当视图变化时,定制小程序开发费用所对应的数据也随之改变,通过MVVM实现数据与视图的双向绑定。
  • VUE定制小程序开发费用是渐进式框架,VUE定制小程序开发费用提供了一个核心库,定制小程序开发费用用于渲染视图,定制小程序开发费用它占空间小,能完成VUE定制小程序开发费用中的常规基础操作。同样VUE定制小程序开发费用根据需求不同还提供多个插件,定制小程序开发费用以方便实现不同的功能。定制小程序开发费用这种在核心库基础上可定制小程序开发费用以根据需要递增使用不定制小程序开发费用同的插件这种方式称为渐进式。
  • VUE定制小程序开发费用是做单页面应用的最佳选择。
  • VUE定制小程序开发费用在内存中构建DOM结构,定制小程序开发费用并一次性进行渲染,定制小程序开发费用在效率上要比jQuery这类操作DOM定制小程序开发费用的库高很多,另外VUE定制小程序开发费用让开发人员减少了DOM操作,定制小程序开发费用使用起来要比jQuery定制小程序开发费用类的库方便很多。
  • VUE语法简单,定制小程序开发费用比较容易上手,定制小程序开发费用且功能强大。

Vue定制小程序开发费用的基本使用

VUE定制小程序开发费用有两种使用方式:

  • 直接使用VUE.js,定制小程序开发费用该方式以常规编码的形式实现VUE定制小程序开发费用中各个功能,便于理解VUE定制小程序开发费用各个功能的实现,定制小程序开发费用适合学习阶段。
  • VUE-CLI,使用VUE定制小程序开发费用脚手架定制小程序开发费用的方式构建VUE环境,定制小程序开发费用该方式基于node实现,定制小程序开发费用能快速搭建VUE定制小程序开发费用模块开发环境。使用方便,定制小程序开发费用适合生产阶段(定制小程序开发费用提高开发效率)

定制小程序开发费用我们先使用VUE.js的方式构建VUE项目,定制小程序开发费用通过常规编码使用了解VUE定制小程序开发费用中各个模块的使用;定制小程序开发费用最后在通过的方式构建VUE开发环境。

Vue.js的基本使用步骤

Vue官网下载vue.js文件

两个版本:

  • vue.js开发版,其中有vue的完整代码,格式方便查看源代码,想研究源代码的可以使用此版本
  • vue.min.js生产版,压缩后的版本,代码中删除了无效的字符和空格,代码紧凑,体积较小,不便于查看源码

在HTML页面中引入vue.js文件

<script src="js/vue.js"></script>

创建Vue实例,并设置相关选项

  • el:指定Vue要渲染的元素,在vue.js中只有放在渲染元素中vue才起作用,渲染的元素可以是div、body等任意HTML元素,开发中一般使用div。

  • data:VUE的数据属性区,在此区域中定义VUE中要使用的相关属性数据。

  • methods:VUE的方法区,在此区域中定义VUE中要使用的方法(函数)。

  • template:用于定义组件模板,VUE中的HTML元素标签、VUE相关指令都可以在此区域定义,运行时会进行渲染并在页面中显示,template的渲染优先级高于el指定的渲染元素,也就是说如果在template中和el渲染元素中都定义的内容,则显示的结果为template中的内容,而el中指定的渲染元素不会显示,如果没有template则会显示el指定的渲染元素。

  • created:created()函数是VUE实例创建后自动执行的函数,可以在该函数中初始化data属性、发送等操作。

  1. <script src="../js/vue.min.js"></script>
  2. <script>
  3. /*创建VUE实例(注意Vue的V是大写的),并设置相关选项*/
  4. new Vue({
  5. el: "#app",/*通过id选择器指定要渲染的元素*/
  6. data() { /*数据属性区,其中定义相关属性*/
  7. return {
  8. name: "关为",
  9. age: 18,
  10. sex: "男"
  11. }
  12. },
  13. methods: {/*方法区,其中定义功能函数*/
  14. showMsg() {
  15. //方法中调用属性需要使用this关键字调用
  16. console.log(this.name);
  17. },
  18. showClick() {
  19. alert("你好,欢迎来到召唤师峡谷!");
  20. }
  21. },
  22. created() {/*created函数,在vue实例创建后自动执行*/
  23. //调用方法区中的方法需要使用this关键字
  24. this.showMsg();
  25. },
  26. /*
  27. 模板区中的内容使用模板字符串括起来
  28. 渲染优先级高于el指定的渲染元素
  29. */
  30. template: `
  31. <div>模板区显示</div>
  32. `
  33. });
  34. </script>

在页面或模板中使用属性

VUE中通过插值运算符{{}}来访问data区中的属性

  1. <div id="app">
  2. <!--获得data中的属性值-->
  3. <p>{{name}}</p>
  4. <!--字符串原样显示-->
  5. <p>{{"西安欢迎您"}}</p>
  6. <!--进行计算并显示-->
  7. <p>{{10+2}}</p>
  8. </div>

VUE 中的插值运算符不但可以获取data中的属性还可以进行计算并显示,如果要显示字符串常量则需要加上单引号或双引号否则vue会当成属性名获取该属性的值 。

VUE 通过事件调用方法 

VUE 中通过 v-on:事件="函数()"来调用函数也可以通过缩写形式@事件名调用函数

  1. <div id="app">
  2. 姓名:{{name}}<br/>
  3. 年龄:{{age}}
  4. <hr/>
  5. <!--注意:必须写在被绑定的div中-->
  6. <button @click="funA()">缩写函数调用</button>
  7. <button v-on:click="funB()">标准函数调用</button>
  8. <button @click="age++">操纵属性</button>
  9. <button @click="funC()">操纵属性</button>
  10. </div>
  11. <script src="../js/vue.min.js"></script>
  12. <script>
  13. new Vue({
  14. el: '#app',
  15. data() {
  16. return {
  17. id: 1,
  18. name: '关为',
  19. age: 19
  20. }
  21. },
  22. methods: {
  23. funA() {
  24. console.log(this.name+"输出了一段内容!");
  25. },
  26. funB() {
  27. console.log(this.name);
  28. },
  29. // 函数的复杂写法
  30. funC: function(param) {
  31. this.name = "关老师";
  32. }
  33. }
  34. });
  35. </script>

Vue 中的选项

根实例中的 data 选项

Vue 的数据属性区,在此区域中定义 VUE 中要使用的相关属性数据。也可以看成是变量定义区域。

  1. <div id="app">
  2. {{name}}
  3. </div>
  4. <script>
  5. // data选项对象的写法
  6. new Vue({
  7. el:'#app',
  8. data:{
  9. name:'对象的写法'
  10. }
  11. });
  12. // data选项函数的写法--标准
  13. new Vue({
  14. el:'#app',
  15. data:function (){
  16. return {
  17. name:'函数标准写法'
  18. }
  19. }
  20. });
  21. // data选项函数的写法--缩写
  22. new Vue({
  23. el: '#app',
  24. data() {
  25. return {
  26. name: '函数缩写写法'
  27. }
  28. }
  29. });
  30. </script>

Vue 指令

什么是 Vue 的指令

  • 在 VUE 中在页面上提供了一套便于页面和数据交互的操作,这些操作就叫做指令,VUE 中的指令都是以"v-xxx"的形式表示。如: <div v-xxx></div>

  • 每个 VUE 指令完成一个功能,VUE 指令中封装了一些 DOM 行为,通过指令的属性赋值,根据不同的值,VUE 会进行相应的 DOM 操作,以完成既定的功能。

Vue 中常用的指令

v-text:等同于 DOM 中的 innerText 属性,用于向标签体中写入文本,该指令和{{}}的功能一样,使用较少(注:该指令不会对 HTML 元素进行解释执行,而是原样输出)。

  1. <!--name是data中定义的一个变量名-->
  2. <div id="app" v-text="name"></div>

v-html:等同于 DOM 中的 innerHTML 属性,用于向标签体中写入文本(注:该指令会对HTML元素进行解释执行)。

  1. <!--name是data中定义的一个变量名-->
  2. <div id="app" v-html="name"></div>

v-bind:设置元素属性指令,如:v-bind:href="数据属性|表达式",一般使用简写方式:href="数据属性|表达式",其实简单的说,就是给属性赋予定义变量的值。

  1. <div id="app">
  2. <h1>基本写法</h1>
  3. <!--标准形式 这里的content就是变量名-->
  4. 绑定文本框:<input type="text" v-bind:value="content"/><br/>
  5. <!--缩写(语法糖)形式-->
  6. 绑定文本框:<input type="text" :value="content"/><br/>
  7. <!--原封不动的显示content文字-->
  8. 非绑定文本框:<input type="text" value="content"/>
  9. <hr/>
  10. <h1>动态绑定对象</h1>
  11. <span>{{i}}</span><br/>
  12. <input type="text" :value="i"/><br/>
  13. <button @click="i++">点击我改变i的值</button>
  14. <hr/>
  15. <h2 v-bind:class="{active:isActive,line:isLine}">{{content}}</h2>
  16. <h2 :class="{active:isActive,line:isLine}">{{content}}</h2>
  17. <!--这里的url就是变量名,在data中定义的变量-->
  18. <a :href="url">动态连接</a><br/>
  19. <a v-bind:href="url">动态连接</a>
  20. <button @click="changeColor">改变class</button>
  21. </div>
  22. <script>
  23. new Vue({
  24. el: '#app',
  25. data() {
  26. return {
  27. content: '动态的内容',
  28. i: 1,
  29. isActive: true,
  30. isLine: true,
  31. url: 'https://www.baidu.com'
  32. }
  33. },
  34. methods: {
  35. changeColor() {
  36. this.isActive = !this.isActive;
  37. }
  38. }
  39. });
  40. </script>

v-if:等同于JavaScript中的if判断,当条件为true时显示页面内容,为false时不显示。

  1. <!--生成一个随机数 分支案例中都会用到这个-->
  2. <script>
  3. new Vue({
  4. el: '#app',
  5. data() {
  6. return {
  7. number: 1
  8. }
  9. },
  10. methods: {
  11. funA() {
  12. let random = Math.floor(Math.random() * 100 + 1);
  13. this.number = random;
  14. }
  15. },
  16. created() {
  17. // 页面加载时 执行函数funA()
  18. this.funA();
  19. }
  20. });
  21. </script>
  22. <!--当条件为true时显示数字是偶数-->
  23. <span v-if="number%2==0">
  24. {{number}}是偶数
  25. </span>

v-show:该指令与v-if的效果一样,当值为true时显示内容,为false时不显示,但底层实现有区别。

  1. <span v-show="number>60">
  2. {{number}}大于60!
  3. </span>

v-if 和 v-show 的区别?

  • v-if是"真正"的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
  • v-if也是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块。
  • 相比之下,v-show就简单多了,它不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换(通过修改display样式来进行显示或隐藏)。
  • 一般来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show较好;如果在运行时条件很少改变,则使用v-if较好。

v-else-if:等同于JavaScript中的else if判断,当条件为true时显示条件块中的内容,v-else-if一般和v-if搭配使用。
v-else:等同于JavaScript中else判断,当if条件不成立时自动显示else中的元素,v-else和v-if|或v-if-else搭配使用。

  1. <span v-if="number==100">
  2. {{number}},完美!
  3. </span>
  4. <span v-else-if="number>=90">
  5. {{number}},优秀!
  6. </span>
  7. <span v-else-if="number>=75">
  8. {{number}},良好!
  9. </span>
  10. <span v-else-if="number>=60">
  11. {{number}},及格!
  12. </span>
  13. <span v-else>
  14. {{number}},很差!
  15. </span>

v-on:事件绑定指令,如v-on:click="方法",一般使用简写方式@click="方法"。

  1. <button @click="funA()">缩写函数调用</button>
  2. <button v-on:click="funB()">标准函数调用</button>

v-for:遍历指令,主要用于遍历集合或对象中的属性。

  1. <div id="app">
  2. <!--遍历1-10-->
  3. <span v-for="i in 10">
  4. <b>{{i}}</b>&nbsp;
  5. </span>
  6. <hr/>
  7. <!--遍历数组中的元素-->
  8. <span v-for="name in names">
  9. <b>{{name}}</b>&nbsp;
  10. </span>
  11. <hr/>
  12. <!--遍历数组中的元素 带索引号-->
  13. <span v-for="(name,index) in names">
  14. <b>{{index}}->{{name}}</b>&nbsp;
  15. </span>
  16. <hr/>
  17. <!--遍历对象的属性值-->
  18. <span v-for="value in users">
  19. <b>{{value}}</b>&nbsp;
  20. </span>
  21. <hr/>
  22. <!--遍历对象的属性值 (值,键)-->
  23. <span v-for="(value,key) in users">
  24. <b>{{key}}--->{{value}}</b>&nbsp;
  25. </span>
  26. <hr/>
  27. <!--遍历对象的属性值 (值,键,索引号)-->
  28. <span v-for="(value,key,index) in users">
  29. <b>{{key}}--->{{value}}--->{{index}}</b>&nbsp;
  30. </span>
  31. </div>
  32. <script>
  33. new Vue({
  34. el: '#app',
  35. data() {
  36. return {
  37. names: ['张三', '李四', '王五', '关为', '马六', '刘德华'],
  38. users: {
  39. userId: 1,
  40. userName: '张三',
  41. userSex: '男',
  42. userAge: 19
  43. }
  44. }
  45. }
  46. });
  47. </script>

v-model:该指令用于实现数据与视图的双向绑定,当数据改变时视图发生改变,视图改变时数据也同时发生改变,v-model只能在带有value属性的HTML元素中使用。

  1. <div id="app">
  2. <!--双向绑定实现原理-->
  3. <!--绑定了遍历val,如果val发生改变这里也发生改变,这里发生改变也会影响到遍历val的内容从而影响到下边文本框的内容-->
  4. <input type="text" v-model="val"/>
  5. <input type="text" :value="val" @input="changeValue"/>
  6. {{val}}
  7. </div>
  8. <script>
  9. new Vue({
  10. el: '#app',
  11. data() {
  12. return {
  13. val: 'hello'
  14. }
  15. },
  16. methods: {
  17. changeValue(e){
  18. // e.target获得事件源对象
  19. this.val = e.target.value;
  20. }
  21. }
  22. });
  23. </script>

v-bind 和 v-model 的区别? 

  • v-bind是单向绑定,用来绑定数据和属性以及表达式,只能将vue中的数据同步到页面。
  • v-model是双向绑定,不只能将vue中的数据同步到页面,而且可以将用户数据的数据赋值给vue中的属性。
  • v-bind可以给任何属性赋值,v-model只能给具备value属性的元素进行数据双向绑定。

Vue 组件

组件系统是 Vue 的一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:

组件用于封装页面的部分功能,将功能的结构、样式、逻辑代码封装为整体。这样,当我们页面的某一个功能出现问题,只需要将这个功能进行维护就行。提高功能的复用性与可维护性,更好的专注于业务逻辑。

从形式来说,Vue组件其实就是自定义的HTML标签,通过组件名来作为自定义标签名。我们可以把页面的一些功能封装成自定义的HTML标签,也就是Vue组件的形式,当使用时,只需要调用Vue组件就行。

  1. <div id="app">
  2. <b>HTML的b标签</b>
  3. <!--全局组件 就是一个自定义HTML标签 不要书写成<guanwei/>-->
  4. <guanwei></guanwei>
  5. </div>

这里面的<guanwei></guanwei>标签就是Vue组件,它是封装好的功能,使用时,只需调用这个标签就行。 

组件注册

1. 全局组件

1.1 全局组件的基本使用

全局注册的组件在注册后可以用于任意实例或组件中。

Vue.component('组件名', {/*选项对象*/});

注意:

  • 全局注册必须设置在根Vue实例创建之前。
  • 全局组件只能使用在根Vue绑定的标签内。 
  1. <div id="app">
  2. <b>HTML的b标签</b>
  3. <!--全局组件 就是一个自定义HTML标签 不要书写成<guanwei/>-->
  4. <guanwei></guanwei>
  5. </div>
  6. <hr/>
  7. <!--错误,必须在绑定的根实例内使用-->
  8. <guanwei></guanwei>
  9. <script src="../js/vue.min.js"></script>
  10. <script>
  11. // 注册全局组件 V必须大写 全局注册必须设置在Vue根实例创建之前。
  12. Vue.component('guanwei', {
  13. template: '<b>我是自定义的组件关为</b>'
  14. });
  15. // Vue根实例
  16. new Vue({
  17. el: '#app'
  18. });
  19. </script>

1.2 组件命名规则

无论全局组件还是局部组件都具有两种命名规则:

  • kebab-case:'guan-wei'
  • PascalCase:'GuanWei'
  1. // kebab-case写法
  2. Vue.component('guan-wei1', {/*组件选项*/});
  3. // PascalCase写法
  4. Vue.component('GuanWei2', {/*组件选项*/});

注意:无论采用哪种命名方式,在DOM中都只能通过kebab-case可以使用。因为HTML中不区分大小写。

  1. <div id="app">
  2. <guan-wei1></guan-wei1>
  3. <!--PascalCase写法使用时必须使用kebab-case来获取 这里获取不到-->
  4. <GuanWei2></GuanWei2>
  5. <!--正确的引用方式-->
  6. <guan-wei2></guan-wei2>
  7. </div>

2. 组件基础

本职上,组件是可重复的Vue实例,所以它们可与new Vue接收相同的选项,例如data、methods以及生命周期钩子等。

注意:el这个选项是根实例特有的,组件中不能进行设置。

2.1 template选项

template选项用于设置组件的结构,最终被引入根实例或其他组件中。

  1. Vue.component('guan-wei1', {
  2. template: `
  3. <div>
  4. <b>我是组件内的标签1</b>
  5. </div>
  6. `
  7. });

注意:template中不能有平级的根实例,如果有多个平级的div,只会显示第一个div的内容。 

  1. <script>
  2. Vue.component('guan-wei1', {
  3. template: `
  4. <div>
  5. <b>我是组件内的标签1</b>
  6. </div>
  7. `
  8. });
  9. Vue.component('guan-wei2', {
  10. template: `
  11. <div>
  12. <b>我是组件内的标签2</b>
  13. <b>我是组件内的标签2</b>
  14. </div>
  15. `
  16. });
  17. // ✖ template中只能有一个根实例 不能有平级实例 第二个div不会显示
  18. Vue.component('guan-wei3', {
  19. template: `
  20. <div>
  21. <b>我是组件内的标签31</b>
  22. </div>
  23. <div>
  24. <b>我是组件内的标签32</b>
  25. </div>
  26. `
  27. });
  28. new Vue({
  29. el: '#app'
  30. });
  31. </script>

2.2 data选项

data选项用于存储组件的数据,与根实例的data不同,组件的data选项必须为函数,数据设置在返回值对象中。

  1. Vue.component('guan-wei1',{
  2. template:'<b>{{name}}</b>',
  3. data:function (){
  4. return {
  5. name:'关为'
  6. }
  7. }
  8. })

使用函数写法的目的是因为data中定义的每一个变量都是独立的存在,不同的实例(<guan-wei1></guan-wei1>)都有各自独立的变量name,其中一个name的值发生改变,其他实例的name值不受干扰。 

例如,如下实例:

  1. <div id="app">
  2. <!--定义了3个guan-wei1全局组件的实例-->
  3. <guan-wei1></guan-wei1><br/>
  4. <guan-wei1></guan-wei1><br/>
  5. <guan-wei1></guan-wei1>
  6. </div>
  7. <script>
  8. Vue.component('guan-wei1', {
  9. template: '<b>{{age}}</b>',
  10. data: function () {
  11. return {
  12. age: Math.floor(Math.random() * 100 + 1) // 年龄随机,每个实例的年龄都不相同
  13. }
  14. }
  15. });
  16. new Vue({
  17. el: '#app'
  18. });
  19. </script>

3. 局部组件

局部注册的组件只能用在当前实例或组件中。

3.1 直接书写组件选项

  1. new Vue({
  2. el: '#app',
  3. ....
  4. components: {
  5. '组件名': {/*组件选项*/},
  6. '组件名': {/*组件选项*/},
  7. ....
  8. }
  9. });

3.2 单独配置组件的选项对象 

  1. // 单独配置组件的选项对象
  2. let guanwei = {/*组件选项*/};
  3. new Vue({
  4. el: '#app',
  5. components: {
  6. '组件名': guanwei
  7. }
  8. });

3.3 ES6 简写形式

  1. let guanwei = {/*组件选项*/};
  2. // ES6简写形式 兼容性较差
  3. new Vue({
  4. el:'#app',
  5. components: {
  6. // 这里直接引入变量名就行,那么组件名也是guanwei,自定义标签<guanwei></guanwei>
  7. guanwei
  8. }
  9. })

4. 全局注册和局部注册的区别 

全局注册的组件能够被不同根实例所使用,而局部组件只能在当前根实例中使用。

  1. <div id="app">
  2. <guan-wei1></guan-wei1>
  3. <guan-wei2></guan-wei2>
  4. </div>
  5. <hr/>
  6. <div id="app2">
  7. <!--全局组件在这里可以使用 因为全局组件能够被所有实例使用-->
  8. <guan-wei2></guan-wei2>
  9. <!--这里看不到效果,因为局部组件注册到了app中-->
  10. <guan-wei1></guan-wei1>
  11. </div>
  12. <script src="../js/vue.min.js"></script>
  13. <script>
  14. Vue.component('guan-wei2',{
  15. template: '<b>全局组件关为</b>'
  16. });
  17. new Vue({
  18. el: '#app',
  19. components: {
  20. 'guan-wei1': {
  21. template: '<b>局部组件关为</b>'
  22. }
  23. }
  24. });
  25. new Vue({
  26. el: '#app2'
  27. });
  28. </script>

组件通信

在组件间传递数据的操作,称为组件通信。

1. 父组件向子组件传值

通过子组件的 props 选项接收父组件的传值。

  1. <!--父组件-->
  2. <div id="app">
  3. <!--三个子组件-->
  4. <!--静态内容写法-->
  5. <guan-wei id="2" name="张三" did="20" dname="销售部"></guan-wei>
  6. <!--动态绑定写法 传递静态内容-->
  7. <guan-wei v-bind:id="3" :name="'李四'" :did="30" :dname="'财务部'"></guan-wei>
  8. <!--动态绑定写法 父组件给子组件传值-->
  9. <guan-wei :id="id" :name="name" :did="dept.id" :dname="dept.dname"></guan-wei>
  10. </div>
  11. <script src="../js/vue.min.js"></script>
  12. <script>
  13. Vue.component('guan-wei', {
  14. props: ['id', 'name', 'did', 'dname'],
  15. template: `
  16. <div>
  17. <b>编号:{{ id }}</b><br/>
  18. <b>姓名:{{ name }}</b><br/>
  19. <b>部门编号:{{ did }}</b><br/>
  20. <b>部门名称:{{ dname }}</b>
  21. </div>
  22. `
  23. })
  24. new Vue({
  25. el: '#app',
  26. data: {
  27. id: 1,
  28. name: '关为',
  29. dept: {
  30. id: 10,
  31. dname: '研发部'
  32. }
  33. }
  34. });
  35. </script>

注意:

  1. 子组件 props 不要与子组件的 data 存在同名属性。
  2. props 选项是一个数组形式,其中的值(prop)可以看成是组件(自定义标签)的属性。
  3. 父子组件间的所有 prop 都是单向下行绑定的,只能从父组件向子组件传值。
  4. 动态绑定以 :prop 或者 v-bind:prop 命名。
  5. 动态绑定时,如果要传递常量字符串需要使用''将字符串给包含,如果不加''认为是父组件中的变量名。

Props 命名规则 

建议 prop 命名使用 camelCase ,父组件绑定时使用 kebab-case 。因为 props 中定义的 prop 是书写在 JavaScript 中的,是区分大小写的,而页面中标签的引用是 HTML 效果,HTML 不区分大小写。

  1. <!--html 标签引用 名称是 kebab-case 方式-->
  2. <guan-wei user-id="1" :user-name="'关为'" v-bind:user-age="19" user-sex="男"></guan-wei>
  3. Vue.component('guan-wei', {
  4. // prop 的命名以驼峰形式书写
  5. props: ['userId', 'userName', 'userAge', 'userSex']
  6. })

2. 子组件向父组件传值

子组件通过自定义事件的方式向父组件传值。

  1. <!--
  2. 子组件通过事件向父组件传值
  3. 1.当点击子组件的+1按钮时,触发了函数 addNumber2
  4. 2.在函数 addNumber2 中执行了子组件变量 number2 自增和触发了自定义事件 guan
  5. 3.@guan事件触发后执行了函数 addNumber1 自增了 number1 的值
  6. -->
  7. <div id="app">
  8. <b>{{number1}}</b>
  9. <guanwei @guan="addNumber1()"></guanwei>
  10. </div>
  11. <script src="../js/vue.min.js"></script>
  12. <script>
  13. Vue.component('guanwei', {
  14. data() {
  15. return {
  16. number2: 1
  17. }
  18. },
  19. template: `
  20. <div>
  21. <b>{{ number2 }}</b>
  22. <button @click="addNumber2">+1</button>
  23. </div>
  24. `,
  25. methods: {
  26. addNumber2() {
  27. // 触发了自定义事件guan
  28. this.$emit('guan');
  29. this.number2++;
  30. }
  31. }
  32. })
  33. new Vue({
  34. el: '#app',
  35. data() {
  36. return {
  37. number1: 1
  38. }
  39. },
  40. methods: {
  41. addNumber1() {
  42. this.number1++;
  43. }
  44. }
  45. });
  46. </script>

练习

通过子组件向父组件传值的方式完成如下效果

 

一共有四个子组件,当点击每一个按钮时,子组件的数量自增1,同时父组件书籍总量的值也会自增1。 

刚才的案例中,我们了解到了当子组件触发事件时,父组件可以监控到子组件的触发,那么如何直接在子组件中向父组件传递具体的值呢?

子组件触发事件时可以向父组件传值。

  1. // 触发了自定义事件guan 并且传递了当前文本框的值和一个常量字符串
  2. this.$emit('guan',e.target.value,'aa');

父组件在监听事件时需要接受子组件传递的数据。

  1. // 这里的的参数a和b就是事件传递过来的值
  2. addNumber1(a,b) {
  3. this.number1 = a + ',' + b;
  4. }

3. 非父子组件传值

非父子组件指的是兄弟组件或完全无关的两个组件。

3.1 兄弟组件传值

兄弟组件之间可以通过父组件进行数据中转。

  1. <div id="app">
  2. 组件1:
  3. <guanwei01 @guan="change01"></guanwei01>
  4. <br/>
  5. 父组件:{{value}}<br/>
  6. 组件2:<guanwei02 :value02="value"></guanwei02>
  7. </div>
  8. <script src="../js/vue.min.js"></script>
  9. <script>
  10. // 第一个组件,当这个组件文本框的值发生改变时,将文本框的值传递给父组件
  11. Vue.component('guanwei01', {
  12. data() {
  13. return {
  14. value01: 'a'
  15. }
  16. },
  17. template: `
  18. <div>
  19. <input v-model="value01"/>
  20. <button @click="changeComponent">点击我</button>
  21. </div>
  22. `,
  23. methods: {
  24. changeComponent() {
  25. // 触发了guan事件 并将value的值传递出去了
  26. this.$emit('guan', this.value01);
  27. }
  28. }
  29. });
  30. // 第二个组件,负责接收父组件传递过来的值
  31. Vue.component('guanwei02', {
  32. props: ['value02'],
  33. template: `
  34. <div>
  35. {{ value02 }}
  36. </div>
  37. `
  38. });
  39. new Vue({
  40. el: '#app',
  41. data: {
  42. value: '原始的值'
  43. },
  44. methods:{
  45. change01(a) {
  46. // 将传递过来的参数赋予变量value
  47. this.value = a;
  48. }
  49. }
  50. });
  51. </script>

3.2 EventBus 传值

当组件嵌套关系复杂时,根据组件关系传值会较为繁琐。组件为了数据中转,data 中会存在许多与当前组件功能无关的数据。

有没有一种方式能够让任意组件直接进行传值,而不需要找到组件与组件之间的关系在进行中转操作呢?

EventBus(事件总线)是一个独立的事件中心,用于管理不同组件间的传值问题。

好处是:

  • 组件和组件之间不需要设置多余的 data 数据。
  • 组件和组件不需要找到之间的关系,只需要 EventBus 中心中进行处理就行。

EventBus 仅仅存储的用来进行传值操作的事件功能,而不会真正的通过 EventBus 来存储数据。它只是一个中转操作。

EventBus 通过一个新的 Vue 实例来管理组件传值操作,组件通过给实例注册事件、调用事件来实现数据传递。

  1. // EventBus 通过一个新的 Vue 实例来管理,新的 Vue 实例不需要设置事件选项。空的 Vue 实例。
  2. let bus = new Vue();

EventBus 实现步骤

  1. 发送数据的组件触发 bus 事件,接收的组件给 bus 注册对应事件。
  2. 接收事件的组件给 bus 注册对应事件通过 $on() 操作。
  1. //传值的组件中
  2. 函数(){
  3. bus.$emit('事件名',参数列表);
  4. }
  5. // 接收的组件中 一般写入到组件选项的 created 中
  6. created(){
  7. bus.$on('事件名',(参数列表)=>{函数体});
  8. }

完整的代码内容

  1. <div id="app">
  2. <guanwei01></guanwei01>
  3. <guanwei02></guanwei02>
  4. </div>
  5. <script src="../js/vue.min.js"></script>
  6. <script>
  7. let bus = new Vue();
  8. Vue.component('guanwei01', {
  9. data() {
  10. return {
  11. count: 1
  12. }
  13. },
  14. template: `
  15. <div>
  16. <p>{{ count }}</p>
  17. <button @click="changeCount">+1</button>
  18. </div>
  19. `,
  20. methods: {
  21. changeCount() {
  22. this.count++;
  23. bus.$emit('guan', this.count);
  24. }
  25. }
  26. });
  27. Vue.component('guanwei02', {
  28. data() {
  29. return {
  30. count: 1
  31. }
  32. },
  33. template: `<b>{{ count }}</b>`,
  34. created() {
  35. bus.$on('guan', (yourCount) => {
  36. this.count = yourCount;
  37. });
  38. }
  39. });
  40. new Vue({
  41. el: '#app'
  42. });
  43. </script>

3.3 其他传值方式

4. 其他通信方式

组件插槽

组件插槽可以快捷的设置组件内容。

  1. <div id="app">
  2. <!--组件-->
  3. <guanwei>
  4. <b>我是一段内容</b>
  5. </guanwei>
  6. </div>

1. 单个插槽

如果我们希望组件标签可以像 HTML 标签一样设置内容,那么组件的使用灵活度会很高。

但问题是平常我们书写的组件,组件内部书写的内容会被抛弃。这时候我们如果需要内容生效,就需要组件插槽来实现。

1.1 可以通过 <slot> 进行插槽设置。

  1. <div id="app">
  2. <guanwei>
  3. <b>自己书写的内容</b>
  4. </guanwei>
  5. <guanwei>
  6. 另一段内容<br/>
  7. <span>组件的主体内容</span>
  8. </guanwei>
  9. <guanwei>
  10. <!--只能获取到父组件的 data 数据-->
  11. {{ content }}
  12. </guanwei>
  13. </div>
  14. Vue.component('guanwei',{
  15. template:`
  16. <div>
  17. <b>我是组件的内容</b>
  18. <slot></slot>
  19. </div>
  20. `
  21. });

<slot> 代表的是组件的内容区域, <guanwei> 标签内部书写的内容会自动替换<slot> 位置的内容,这样在多次使用<guanwei> 自定义标签时,可以传递不同的内容来达到快速传值的目的。有点像我们在 Java 中学习的占位符效果,<slot> 就是占位符,自定义中的内容就是要传递的值。

1.2 可以在 <slot> 中为插槽设置默认值

  1. Vue.component('guanwei',{
  2. template:`
  3. <div>
  4. <b>我是组件的内容</b>
  5. <slot>我是插槽的默认值</slot>
  6. </div>
  7. `
  8. });

2. 具名插槽

如果组件中有多个位置需要设置插槽,需要给 <slot> 设置name,这种具有名称的插槽,称为具名插槽。

2.1 具名插槽的写法

  1. <guanwei>
  2. <!--template标记没有其他作用 就是标识当前内容是赋予那个slot。v-slot:名字-->
  3. <template v-slot:top>
  4. {{title}}
  5. </template>
  6. <template v-slot:default>
  7. {{content}}
  8. </template>
  9. <template v-slot:bottom>
  10. {{bottom}}
  11. </template>
  12. </guanwei>
  13. Vue.component('guanwei', {
  14. template: `
  15. <div>
  16. <h1>我是头部部分</h1>
  17. <slot name="top"></slot>
  18. <h1>我是中间部分</h1>
  19. <slot>我的默认名字是default</slot>
  20. <h1>我是底部部分</h1>
  21. <slot name="bottom"></slot>
  22. </div>
  23. `
  24. });

2.2 具名插槽的缩写形式

  1. <guanwei>
  2. <!--可以使用#name的写法,其中默认的部分可以忽略 <template>-->
  3. <template #top>
  4. {{title}}
  5. </template>
  6. {{content}}
  7. <template #bottom>
  8. {{bottom}}
  9. </template>
  10. </guanwei>

3. 作用域插槽

前边所学到的插槽中只能使用父组件的 data 数据,那么如何能够在插槽中使用子组件的数据呢?

这时候我们就会用到作用域插槽。那么如何设置呢?

组件将需要被插槽使用的数据通过 v-bind:要传递的变量名="要传递的变量名" 绑定给 <slot> ,这种用于给插槽传递数据的属性称为插槽 prop 。

  1. <div id="app">
  2. <guanwei>
  3. <!--gwObj是子组件的实例 可以通过子组件的实例获取数据-->
  4. <template v-slot:default="gwObj">
  5. 父组件内容:{{content}}<br/>
  6. 子组件内容:{{gwObj.content}}
  7. </template>
  8. </guanwei>
  9. </div>
  10. <script src="../js/vue.min.js"></script>
  11. <script>
  12. Vue.component('guanwei', {
  13. template: `
  14. <div>
  15. <h3>v-bind:变量名绑定要使用的数据 前后 content 建议一致</h3>
  16. <h4>第一个 content 是我们起的名称供 template 调用,第二个是 变量名</h4>
  17. <slot v-bind:content="content"></slot>
  18. </div>
  19. `,
  20. data() {
  21. return {
  22. title: '子组件的标题',
  23. content: '子组件的内容'
  24. }
  25. }
  26. });
  27. new Vue({
  28. el: '#app',
  29. data: {
  30. title: '父组件的标题',
  31. content: '父组件的内容'
  32. }
  33. });
  34. </script>

内置组件

动态组件

动态组件适用于多个组件频繁切换的处理。

<component> 用于将一个“元组件”渲染为动态组件,以 is 属性值决定渲染那个组件,类似于 v-if 或 v-show 的效果。

  1. <div id="app">
  2. <!--注意这里组件名如果是常量字符串 必须加入''-->
  3. <component :is="组件名"></component>
  4. </div>

用于实现多个组件的快速切换,例如选项卡效果。 

  1. <div id="app">
  2. <component :is="name">{{name}}</component>
  3. <br/>
  4. <button @click="changeName('guanwei01')">guanwei01</button>
  5. <button @click="changeName('guanwei02')">guanwei02</button>
  6. <button @click="changeName('guanwei03')">guanwei03</button>
  7. </div>
  8. <script src="../js/vue.min.js"></script>
  9. <script>
  10. Vue.component('guanwei01', {template: '<div><b>我是组件关为01</b><br/><slot></slot></div>'});
  11. Vue.component('guanwei02', {template: '<div><b>我是组件关为02</b><br/><slot></slot></div>'});
  12. Vue.component('guanwei03', {template: '<div><b>我是组件关为03</b><br/><slot></slot></div>'});
  13. // Vue根实例
  14. new Vue({
  15. el: '#app',
  16. data: {
  17. name: 'guanwei01'
  18. },
  19. methods: {
  20. changeName(n) {
  21. this.name = n;
  22. }
  23. }
  24. });
  25. </script>

is 属性会在每次切换组件时,Vue 都会创建一个新的组件实例。在组件进行切换时都会销毁原有组件,在新建(重新渲染)新的组件。

  1. // 输入框在每次切换时 值都会消失,因为切换组件会导致原有组件销毁并新建新的组件(重新渲染)
  2. Vue.component('guanwei01', {template: '<div><b>我是组件关为01</b><br/><input/></div>'});
  3. Vue.component('guanwei02', {template: '<div><b>我是组件关为02</b><br/><input/></div>'});
  4. Vue.component('guanwei03', {template: '<div><b>我是组件关为03</b><br/><input/></div>'});

keep-alive 组件

主要用于保留组件状态或避免组件重新渲染。

  1. <!--keep-alive 可以使得在切换组件时 避免重新渲染-->
  2. <keep-alive>
  3. <component :is="name">{{name}}</component>
  4. </keep-alive>

include 属性可以指定哪些组件会被缓存。 

  1. <keep-alive include="guanwei01,guanwei02">
  2. <component :is="name">{{name}}</component>
  3. </keep-alive>

exclude 属性指定哪些组件不会被缓存。

  1. <keep-alive exclude="guanwei01,guanwei02">
  2. <component :is="name">{{name}}</component>
  3. </keep-alive>

过渡组件

用于在 Vue 插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡、动画效果。

过滤器

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持)。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号指示。

过滤器的基本使用

定义过滤器

  1. new Vue({
  2. el: '#app',
  3. data: {
  4. content: 'Hello,World!'
  5. },
  6. filters: {
  7. guanwei(value) {
  8. return value.toLowerCase();
  9. }
  10. }
  11. });

使用过滤器

  1. <!-- 在双花括号中 -->
  2. {{ 变量名 | 过滤器名}}
  3. <!-- 在 `v-bind` 中 -->
  4. <div v-bind:id="变量名 | 过滤器名"></div>

过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,guanwei 过滤器函数将会收到 变量名 的值作为第一个参数。 

过滤器的分类

局部过滤器:只能在当前实例中使用的过滤器。

  1. filters: {
  2. capitalize: function (value) {
  3. if (!value) return '';
  4. value = value.toString();
  5. return value.charAt(0).toUpperCase() + value.slice(1);
  6. }
  7. }

全局过滤器:定义在根实例书写之前,可以被所有实例使用。

  1. Vue.filter('capitalize', function (value) {
  2. if (!value) return '';
  3. value = value.toString();
  4. return value.charAt(0).toUpperCase() + value.slice(1);
  5. })

注意:当全局过滤器和局部过滤器重名时,会采用局部过滤器。 

传入多个参数

在定义过滤器时,我们可以接受多个参数值,其中第一个参数永远是固定的,它都是要过滤的文本信息,其他参数值根据需要可以灵活设置。

定义过滤器

  1. Vue.filter('guanwei', function (value, a, b) {
  2. if (!value) {
  3. return '';
  4. }
  5. return value.substr(a, b);
  6. });

其中,这里的 value 就是要过滤的文本信息,a 和 b 是传递过来的其他值。 

使用过滤器

  1. <div id="app">
  2. {{ content | guanwei(begin,count) }}
  3. </div>

content 是要传递过去的第一个参数,而 being 和 count 是传递过去的第二个和第三个参数。 

过滤器链

过滤器还可以串联:

{{ content|guanwei01|guanwei02}}

在这个例子中,guanwei01 被定义为接收单个参数的过滤器函数,表达式 content 的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数 guanwei02,将 guanwei01 的结果传递到 guanwei02 中。 

监听器

VUE 中的监听器 watch 用于监听 data 中的各个属性,当所监听的属性值发生改变时,监听器就会被自动执行。

监听单个属性

  1. <script>
  2. // vm 起名字是为了另一种写法调用
  3. let vm = new Vue({
  4. el: '#app',
  5. data: {
  6. message: '初始内容'
  7. },
  8. watch: {
  9. message: function (newValue, oldValue) {
  10. console.log(this.message + '内容被修改了');
  11. console.log('原来的内容是:' + oldValue);
  12. console.log('修改后内容是:' + newValue);
  13. }
  14. }
  15. });
  16. // 也可以书写成这种形式,注意 vm 是根实例名称
  17. vm.$watch('message', function (newValue, oldValue) {
  18. console.log('全局监听属性:' + newValue + "," + oldValue);
  19. });
  20. </script>

监听对象属性

监听复杂类型就需要使用到”深度监听“(deep:true) 。 

  1. new Vue({
  2. el: '#app',
  3. data: {
  4. stu: {
  5. id: 1,
  6. name: '张三'
  7. }
  8. },
  9. watch: {
  10. stu: {
  11. deep: true, //深度监听,消耗性能
  12. handler: function (newValue) {
  13. // 这里的 newValue 都是代表 stu 对象 只能获取到新值
  14. console.log('修改了stu对象的值,name的新值:' + newValue.name);
  15. }
  16. }
  17. }
  18. });

还有其他几种方式,这里就不一一讲解了。 

计算属性 

计算属性也属于监听的一种,单独的监听器只能监听一个属性,当我们在一个功能中需要监听多个属性时,我们就可以使用“计算属性”来实现,计算属性中可以监听多个属性,当所监听的属性中任意一个被修改时,计算属性就会自动执行。

  1. <div id="app">
  2. <img :src="'../img/'+getSrc" width="800" height="600"/>
  3. {{getName}}
  4. <ul>
  5. <li v-for="(item,index) in imageData" @click="clickHandler(index)">
  6. <h3>编号:{{item.id}}-介绍:{{item.name}}</h3>
  7. <p>路径:{{item.src}}</p>
  8. </li>
  9. </ul>
  10. </div>
  11. </body>
  12. </html>
  13. <script src="../js/vue.min.js"></script>
  14. <script>
  15. new Vue({
  16. el: "#app",
  17. data() {
  18. return {
  19. imageData: [
  20. {id: 1, name: '家门口的大湖', src: '1.png'},
  21. {id: 2, name: '河对岸树下的猴子', src: '2.png'},
  22. {id: 3, name: '下雪天的景色', src: '3.png'},
  23. {id: 4, name: '家里养的宠物', src: '4.png'},
  24. {id: 5, name: '额 (⊙o⊙)… 这个?', src: '5.png'}
  25. ],
  26. imgIndex: 0
  27. }
  28. },
  29. methods: {
  30. clickHandler(index) {
  31. this.imgIndex = index;
  32. }
  33. },
  34. /**定义计算属性*/
  35. computed: {
  36. /*
  37. 计算属性中默认使用的是getter(获取数据)
  38. 当前函数监控imgData属性和imgIndex属性,当这两个属性任一个
  39. 发生改变时,都会被computed监控到,并执行对应的函数
  40. */
  41. getSrc: function () {
  42. return this.imageData[this.imgIndex].src;
  43. },
  44. getName: function () {
  45. return this.imageData[this.imgIndex].name;
  46. }
  47. }
  48. });
  49. </script>

Vue 路由

Vue-Router 路由是 VUE 中的一个核心插件,该插件用于组件间的切换,在 VUE 中路由是用于选择或指定组件。

Vue-Router 中默认使用的是 hash 模式( VUE 支持多种模式,如 history 和 Abstract 模式,此处只讲 hash 模式),也就是当出现如下的 URL:http://localhost:8080/#/login 在 URL 中带有#号,#号后面的称为 hash 值,它使用 hash 值做为路由使用。

当 hash 值改变时会执行 onhashchange 事件,根据路由指定的组件重新构建 DOM 结构并显示指定的视图。

下边通过一个 JavaScript 的原生案例,理解 Vue 路由的原理。

  1. <html lang="en">
  2. <head>
  3. <meta charset="UTF-8">
  4. <title>路由---原生案例</title>
  5. </head>
  6. <body>
  7. <a href="#/login">用户登录</a>
  8. <a href="#/register">用户注册</a>
  9. <div id="app">
  10. </div>
  11. </body>
  12. </html>
  13. <script>
  14. window.onhashchange = function () {
  15. let hashVal = location.hash;
  16. switch (hashVal) {
  17. case "#/login":
  18. document.getElementById("app").innerHTML = "用户登录";
  19. break;
  20. case "#/register":
  21. document.getElementById("app").innerHTML = "用户注册";
  22. break;
  23. }
  24. }
  25. </script>

Vue 路由的使用

1. 由于 vue-router 是 Vue 的插件,需要单独下载 vue-router,在 Vue-Router 官网中可以直接下载,。注意下载对应版本,这里需要3.X版本。

2. 由于 vue-router 是基于 Vue 的一个核心插件,所有在引入时先引入 Vue 在引入 vue-router。

  1. <script src="../js/vue.js"></script>
  2. <script src="../js/vue-router.js"></script>

3. 使用 router-link 组件来导航。

  1. <router-link to="/gw01">guanwei01</router-link>
  2. <router-link to="/gw02">guanwei02</router-link>
  3. <router-link to="/gw03">guanwei03</router-link>

4. 定义路由组件。

  1. // 定义组件
  2. // 这里要使用局部组件
  3. let guanwei01 = {
  4. template: `
  5. <div>
  6. <b>关为01</b>
  7. </div>
  8. `
  9. };
  10. let guanwei02 = {
  11. template: `
  12. <div>
  13. <b>关为02</b>
  14. </div>
  15. `
  16. };
  17. let guanwei03 = {
  18. template: `
  19. <div>
  20. <b>关为03</b>
  21. </div>
  22. `
  23. };

5. 创建路由实例。

  1. // 创建VueRouter实例对象
  2. let router = new VueRouter({
  3. /*
  4. 在routers中配置路由
  5. 匀速配置多个路由所以此处是一个数组
  6. */
  7. routes: [
  8. {
  9. //配置一个路由
  10. path: '/gw01',//配置路由的访问路径
  11. component: guanwei01//配置当前路由使用的组件 注意没有''
  12. },
  13. {
  14. path:'/gw02',
  15. component: guanwei02
  16. },
  17. {
  18. path:'/gw03',
  19. component: guanwei03
  20. }
  21. ]
  22. })

 6. 注册路由实例。

  1. new Vue({
  2. el:'#app',
  3. // 在路由中注册组件后 这里可以不用注册
  4. components: {
  5. guanwei01, guanwei02, guanwei03
  6. },
  7. router:router // 注册路由实例
  8. });

7. 设置路由出口。

  1. //写到根实例渲染的 div 中
  2. <router-view></router-view>

vue-router 提供了两个在视图中使用路由的标签。

<router-link to=""></router-link>
    router-link 等同于超链接,在执行时,VUE 会将该标签渲染为 a 标签。
    to:等同于超链接中的 href 属性,在执行时,VUE 会将该属性渲染为 href 属性。
<router-view></router-view>
    router-view:该标签时 vue 组件视图的出口,该标签会自动将 vue 组件渲染到视图中。

Vue 命名路由

我们开发时可以使用路由配置中的 path 进行访问,Vue 路由会根据 path 找到对应 component 组件渲染,在 Vue 中除了可以使用 path 访问外还可使用 name 进行访问,此时我们称为命名路由。

html 部分

  1. <router-link :to="{name:'gw01'}">关为01</router-link>
  2. <router-link :to="{name:'gw02'}">关为02</router-link>
  3. <router-link :to="{name:'gw03'}">关为03</router-link>

VueRouter 中的设置

  1. let router = new VueRouter({
  2. routes: [
  3. {
  4. path: '/gw01',
  5. name: 'gw01', // 给路由起了一个名字
  6. component: guanwei01
  7. },
  8. {
  9. path: '/gw02',
  10. name: 'gw02',
  11. component: guanwei02
  12. },
  13. {
  14. path: '/gw03',
  15. name: 'gw03',
  16. component: guanwei03
  17. }
  18. ]
  19. });

Vue 路由传参

在路由跳转时,我们可以借助路由将参数传递到某个组件,在 Vue 中路由传参数的方式有以下几种:

1. 路由路径参数传递。

此传参方式需要在路由配置的路径配置中设置参数占位符,格式":变量名"。

1.1 在路由调用中需要将该参数使用 params 属性传入,格式 :to="{name:'名称',params:{参数名:值}}"。

  1. <router-link :to="{name:'gw01',params:{id:1}}">关为01</router-link>
  2. <router-link :to="{name:'gw02',params:{id:2}}">关为02</router-link>
  3. <router-link :to="{name:'gw03',params:{id:3}}">关为03</router-link>

1.2 在路由配置的路径配置中设置参数占位符,格式":变量名"。

  1. routes: [
  2. {
  3. path: '/gw01/:id', //:id为路径传参的占位符
  4. component: guanwei01,
  5. name: 'gw01'
  6. },
  7. {
  8. path: '/gw02/:id',
  9. component: guanwei02,
  10. name: 'gw02'
  11. },
  12. {
  13. path: '/gw03/:id',
  14. component: guanwei03,
  15. name: 'gw03'
  16. }
  17. ]

1.3 在组件中接收参数,使用 vue 的 router 属性中的 params 接收参数。

  1. let guanwei01 = {
  2. template: `
  3. <div>
  4. <b>关为01的组件</b>
  5. </div>
  6. `,
  7. mounted() {
  8. // this.$route.params.参数名
  9. console.log(this.$route.params.id);
  10. }
  11. };

2. 查询参数传递

此传参方式无需在路由配置中进行任何修改,只要在路由调用时使用query将参数加入即可,加入参数的方式:

<router-link :to="{name:'路由名',query:{参数名:值}}"}">关为</router-link>

在组件中接收参数,使用vue的router属性中的query接收参数

  1. created(){
  2. console.log(this.$route.query.参数名);
  3. }

Vue 路由嵌套

通过路由可以在视图上显示一个组件,如果在一个组件中又要去动态的显示其他组件,此时我们就要使用嵌套路由来实现。

嵌套路由又称子路由,顾名思义,指在一个路由中又定义了一个或多个路由,外部的路由称为主路由,内部的路由称为子路由。

子路由在主路由的配置中通过 children 属性进行配置,子路由的渲染也需要使用 <router-view/> 进行渲染,在显示子路由的位置使用该标签来进行渲染。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. html{
  10. width: 100%;
  11. height: 100%;
  12. }
  13. body{
  14. width: 100%;
  15. height: 100%;
  16. }
  17. .myApp{
  18. width:90%;
  19. height: 100%;
  20. border: 1px solid red;
  21. margin:0 auto;
  22. }
  23. .myHome{
  24. width:100%;
  25. height: 100%;
  26. }
  27. .myHeader{
  28. width: 100%;
  29. height: 15%;
  30. background-color: darkorange;
  31. }
  32. .myMain{
  33. display: flex;
  34. width: 100%;
  35. height: 85%;
  36. }
  37. .myAsside{
  38. width: 10%;
  39. height: 100%;
  40. background-color:powderblue;
  41. }
  42. .myContent{
  43. width: 90%;
  44. height: 100%;
  45. background-color: lightslategray;
  46. }
  47. </style>
  48. </head>
  49. <body>
  50. <dis id="app"></dis>
  51. <script src="../js/vue.js"></script>
  52. <script src="../js/vue-router.js"></script>
  53. <script>
  54. var Home = {
  55. template:`
  56. <div class="myHome">
  57. <div class="myHeader">头部</div>
  58. <div class="myMain">
  59. <div class="myAsside">
  60. <router-link to="user">用户管理</router-link>
  61. <br/>
  62. <router-link to="goods">商品管理</router-link>
  63. <br/>
  64. <router-link to="sys">系统管理</router-link>
  65. </div>
  66. <div class="myContent">
  67. <!--组件视图出口-->
  68. <router-view></router-view>
  69. </div>
  70. </div>
  71. </div>
  72. `
  73. };
  74. /*用户管理组件*/
  75. var User={
  76. template:`
  77. <div>用户管理</div>
  78. `
  79. };
  80. /*商品管理组件*/
  81. var Goods={
  82. template:`
  83. <div>商品管理</div>
  84. `
  85. };
  86. /*系统管理组件*/
  87. var Sys={
  88. template:`
  89. <div>系统管理</div>
  90. `
  91. }
  92. /*创建路由实例*/
  93. var router = new VueRouter({
  94. routes:[
  95. {
  96. path:"/",//当前路由为根路由
  97. name:"home",
  98. component:Home,
  99. children:[/*此处定义子路由*/
  100. {
  101. path:"user",
  102. component:User
  103. },{
  104. path:"goods",
  105. component:Goods
  106. },{
  107. path:"sys",
  108. component:Sys
  109. }
  110. ]
  111. }
  112. ]
  113. });
  114. new Vue({
  115. el:"#app",
  116. data(){
  117. return{
  118. }
  119. },
  120. router,//挂载路由
  121. template:`
  122. <div class="myApp">
  123. <router-view></router-view>
  124. </div>
  125. `
  126. });
  127. </script>
  128. </body>
  129. </html>

动态路由

在静态路由中要求每个路由对应一个视图组件,如果多个视图显得的风格一致,只是内容不同,那么这时我们可以使用动态路由来共享一个视图组件(组件复用)。

定义组件(这里就定义一个组件)

  1. let guanwei = {
  2. template: `
  3. <div>
  4. <b>动态信息内容是:{{ $route.params.参数名 }}</b>
  5. </div>
  6. `
  7. };

定义路由

  1. let router = new VueRouter({
  2. routes: [
  3. {
  4. path: '/gw/:参数名',
  5. name: 'gw',
  6. component: guanwei
  7. }
  8. ]
  9. });

路由调用 

  1. <router-link :to="{name:'gw',params:{message:'关为01的值'}}">关为01</router-link>
  2. <!--路由调用的简写形式 写法是:'/path/参数'-->
  3. <router-link :to="'/gw/关为02的值'">关为02</router-link>
  4. <router-link :to="{name:'gw',params:{message:'关为03的值'}}">关为03</router-link>

动态路由所共享的组件实例只会被创建一次,如果想在路由切换时要发送ajax请求、处理逻辑等操作就不能使用created函数完成(该函数在组件实例创建后自动执行一次),此时就需要使用watch来监控路由的变化(使用watch监控$route对象)

  1. let guanwei = {
  2. template: `
  3. <div>
  4. <b>动态信息内容是:{{ $route.params.message }},{{ $route.params.message2 }}</b>
  5. </div>
  6. `,
  7. //监控路由的变化,当路由改变时自动触发$route(to,from)函数
  8. watch: {
  9. /*路由变化触发函数
  10. * 参数1:新的路由对象
  11. * 参数2:原来的路由对象
  12. * 通过这两个参数可以获得路由的参数值
  13. */
  14. $route(to, from) {
  15. console.log("to:", to);
  16. console.log("from:", from);
  17. }
  18. }
  19. };

组件缓存

在切换组件视图时,组件会不断的被创建和销毁,此时就没有办法保存组件的状态,如果需要保存组件状态,则就要将组件缓存起来,让组件只被创建一次,以保持组件的状态。使用keep-alive将处于某个视图上的组件缓存起来。

  1. <keep-alive>
  2. <router-view></router-view>
  3. </keep-alive>

全局导航守卫和meta属性的使用

全局导航守卫指当路由的路径发生改变时,它就会监控到,并执行其中的函数。全局导航守卫和 watch 的功能类似,不同之处在于 watch 只负责监控某个组件内部的路由路径变化,而全局导航守卫监控所有组件路由路径的变化导航守卫中的函数会在导航路径发生变化时自动被触发,函数的参数有一下几个:

  1. to:新路径。
  2. form:原路径。
  3. next:next 是一个函数,用于继续执行执行链中下一个地址,如果在函数中不调用 next() 函数,则当前请求就停留在全局导航函数中,而不会继续向下执行,通过 next() 函数还可以指定下一个指定地址的路径。
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. html {
  10. width: 100%;
  11. height: 100%;
  12. }
  13. body {
  14. width: 100%;
  15. height: 100%;
  16. }
  17. .myApp {
  18. width: 90%;
  19. height: 100%;
  20. border: 1px solid red;
  21. margin: 0 auto;
  22. }
  23. .myHome {
  24. width: 100%;
  25. height: 100%;
  26. }
  27. .myHeader {
  28. width: 100%;
  29. height: 15%;
  30. background-color: darkorange;
  31. }
  32. .myMain {
  33. display: flex;
  34. width: 100%;
  35. height: 85%;
  36. }
  37. .myAsside {
  38. width: 10%;
  39. height: 100%;
  40. background-color: powderblue;
  41. }
  42. .myContent {
  43. width: 90%;
  44. height: 100%;
  45. background-color: lightslategray;
  46. }
  47. </style>
  48. </head>
  49. <body>
  50. <dis id="app"></dis>
  51. <script src="../js/vue.min.js"></script>
  52. <script src="../js/vue-router.js"></script>
  53. <script>
  54. var Home = {
  55. template: `
  56. <div class="myHome">
  57. <div class="myHeader">头部</div>
  58. <div class="myMain">
  59. <div class="myAsside">
  60. <router-link to="user">用户管理</router-link>
  61. <br/>
  62. <router-link to="goods">商品管理</router-link>
  63. <br/>
  64. <router-link to="sys">系统管理</router-link>
  65. </div>
  66. <div class="myContent">
  67. <keep-alive>
  68. <router-view></router-view>
  69. </keep-alive>
  70. </div>
  71. </div>
  72. </div>
  73. `
  74. };
  75. /*用户管理组件*/
  76. var User = {
  77. template: `
  78. <div>用户管理</div>
  79. `
  80. };
  81. /*商品管理组件*/
  82. var Goods = {
  83. template: `
  84. <div>
  85. 商品管理
  86. </div>
  87. `
  88. };
  89. /*系统管理组件*/
  90. var Sys = {
  91. template: `
  92. <div>系统管理</div>
  93. `
  94. };
  95. var Login = {
  96. data() {
  97. return {
  98. username: '',
  99. password: ''
  100. }
  101. },
  102. methods: {
  103. login() {
  104. if (this.username == "admin" && this.password == "123456") {
  105. localStorage.setItem('user', {usernmae: this.username, password: this.password});
  106. this.$router.push({path: "goods"});
  107. }
  108. }
  109. },
  110. template: `
  111. <div>
  112. <h3>用户登录</h3>
  113. <input type="text" v-model="username"/>
  114. <input type="password" v-model="password"/>
  115. <button @click="login">登录</button>
  116. </div>
  117. `
  118. }
  119. /*创建路由实例*/
  120. var router = new VueRouter({
  121. routes: [
  122. {
  123. path: "/",//当前路由为根路由
  124. name: "home",
  125. component: Home,
  126. children: [/*此处定义子路由*/
  127. {
  128. path: "user",
  129. component: User
  130. }, {//商品管理
  131. path: "goods",
  132. component: Goods,
  133. meta: {
  134. //控制当前视图是否允许未授权访问
  135. auth: true
  136. }
  137. }, {
  138. path: "sys",
  139. component: Sys
  140. }, {
  141. path: "login",
  142. component: Login
  143. }
  144. ]
  145. }
  146. ]
  147. });
  148. router.beforeEach((to, from, next) => {
  149. //获得localStorage中存储的数据
  150. let user = localStorage.getItem("user");
  151. if (user) {
  152. to.meta.auth = false;
  153. }
  154. //当检测到auth元数据存在时则表示当前组件主要登录后才能访问
  155. if (to.meta.auth) {
  156. next({
  157. path: "login"
  158. });
  159. }
  160. next();
  161. });
  162. new Vue({
  163. el: "#app",
  164. data() {
  165. return {}
  166. },
  167. router,//挂载路由
  168. template: `
  169. <div class="myApp">
  170. <router-view></router-view>
  171. </div>
  172. `
  173. });
  174. </script>
  175. </body>
  176. </html>

Axios 的使用

axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。 axios 的主要用于向服务器发送请求和接收响应,也可以称 axios是一个 Ajax 库,其中封装了 Ajax 的相关操作,方便我们使用 Ajax 与服务器交互。axios 是一个轻量级的 Ajax 库,axios 只负责交互不支持 DOM 的生成,VUE 中没有提供 Ajax 库,在 VUE 中要与服务端交互都会使用第三方 Ajax 进行,一般情况下 VUE 与服务端交互使用Axios 库实现。

Axios 的相关文档请参阅。

Axios 的一些特点:

  • 从浏览器中创建 XMLHttpRequests。
  • 从 node.js 创建 http 请求。
  • 支持 Promise API。
  • 拦截请求和响应。
  • 转换请求数据和响应数据。
  • 取消请求。
  • 自动转换 JSON 数据。
  • 客户端支持防御 XSRF。 

Axios 的搭建

使用 CDN 方式引入 js 文件

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

执行 get 请求 

  1. // 为给定 ID 的 user 创建请求
  2. axios.get('/user?ID=12345')
  3. .then(function (response) {
  4. console.log(response);
  5. })
  6. .catch(function (error) {
  7. console.log(error);
  8. });
  9. // 可选地,上面的请求可以这样做
  10. axios.get('/user', {
  11. params: {
  12. ID: 12345
  13. }
  14. })
  15. .then(function (response) {
  16. console.log(response);
  17. })
  18. .catch(function (error) {
  19. console.log(error);
  20. });

执行 post 请求

  1. let data = new URLSearchParams();
  2. data.append("type", "c");
  3. data.append("a", _this.a);
  4. axios({
  5. method: 'post',
  6. url: 'url',
  7. data: data
  8. }).then((response) => {
  9. console.log(response);
  10. })

执行多个并发请求

  1. function getUserAccount() {
  2. return axios.get('/user/12345');
  3. }
  4. function getUserPermissions() {
  5. return axios.get('/user/12345/permissions');
  6. }
  7. axios.all([getUserAccount(), getUserPermissions()])
  8. .then(axios.spread(function (acct, perms) {
  9. // 两个请求现在都执行完成
  10. }));

关于对 Vue 实例的 data 区域变量赋值问题

  1. getUser() {
  2. // 在 axios 有自身的 this 所以这里需要对外部 this 进行重命名操作
  3. let _this = this;
  4. axios.get('../json/user.json').then(function (response) {
  5. console.log(response.data.users[0].username);
  6. // 这里将获取到的数据赋予了 data 中的 message 变量
  7. _this.message = response.data.users[0].username;
  8. });
  9. }

axios 返回的 response 对象属性分析 

  1. config:是配置部分。
  2. data:是服务器返回的结果数据,也是我们一般使用的内容,axios 一般会自动将内容转换成 json 字符串。
  3. headers: 响应的头信息。
  4. request:原生的 ajax 对象,XMLHttpRequest 对象。
  5. status:响应状态码。
  6. statusText:响应文本信息。

Vue 脚手架的搭建

VueCLI 是一个基于 Vue.js 进行快速开发的完整系统,是官方提供的一个标准化开发平台。在实际前端开发中都会使用 VUE-CLI 构建前端项目。

搭建步骤

1. 在安装 VueCLI 之前需要查看是否安装了 node ,查看方式

如果安装后会显示对应版本,未安装会提示未找到命令,可以到 node 去自行下载安装。 

2. 安装 npm 

  1. #安装NPM
  2. npm install -g cnpm --registry=https://registry.npm.taobao.org
  3. #设置淘宝镜像
  4. npm config set registry https://registry.npm.taobao.org
  5. #查看镜像安装是否成功
  6. npm config get registry

3. 全局安装 VueCLI 

npm install -g @vue/cli

4. 测试 VueCLI 是否安装成功

一些基本命令

  • 安装:npm install -g @vue/cli
  • 升级:npm update -g @vue/cli
  • 卸载:npm uninstall -g @vue/cli
  • 查看版本 vue -V 或  vue --version 

通过脚手架创建 Vue 项目

1. 通过以下命令创建 Vue 脚手架项目

vue create 项目名

注意:

  • 项目名不要使用中文和大写形式,建议 kabeb-case 写法。 
  • 在 cmd 中一定要切换到具体目录下执行 create 操作,这个项目会创建到当前目录下。

2. 执行上边命令后进入选择界面

3. 使用空格键可以选择我们需要的模块, 小括号有*的就是我们选择的模块, 按回车键切换下一步 。

注意:TypeScript 选项也可以不选择,如果选择会创建多个文件,并且入口文件格式会变为  main.ts(原始是 main.js)。 

4. 选择 Vue 版本。

5. 是否使用Class风格装饰器?no

原本是:home = new Vue()创建vue实例
使用装饰器后:class home extends Vue{}

6. 使用Babel与TypeScript一起用于自动检测的填充? yes 

7. 路由使用历史模式? yes

8. 使用什么css预编译器?Less

9. sss校验格式(只进行报错提醒、不严谨模式、正常模式、严格模式)?第一个

10. 代码检查方式?第一个

11. vue-cli 一般来讲是将所有的依赖目录放在 package.json 文件里。

12. 是否在以后的项目中使用以上配置?no


出现如下效果就创建成功!

按照步骤该启动这个项目

  1. cd guanwei01
  2. npm run serve 

启动成功后

打开浏览器就能看到 HelloWorld 页面

提示:关闭项目只需要 ctrl + C 就行。 

Vue 项目结构解析

Vue 项目结构

绿色区域文件:

  • .gitignore:git 的忽略文件,哪些文件或者文件夹不想接受 git 的管理在这里配置。
  • babel.config.js:babel 的控制文件,涉及 ES6 --> ES5 类型转换,一般我们不用管理。
  • package.json:包含了项目依赖模块的列表,类似于 pom.xml 文件。
  • package-lock.json:包版本控制文件,包含了项目依赖模块的一些限制信息(限制版本号,限制下载地址,限制哈希值)
  • README.md:是一个项目的入门手册,里面介绍了整个项目的使用、功能等等。
  • tsconfig.json:如果目录下存在一个 tsconfig.json 文件,那么意味着此目录是 TypeScript 项目的根目录。 tsconfig.json 文件中指定了用来编译这个项目的根文件和编译选项。
  • vue.config.js:当前 vue 项目的配置文件,启动的时候会自动加载。 

文件夹讲解:

public 文件夹:任何放置在 public 文件夹的静态资源都会被简单的复制,而不经过 webpack。你需要通过绝对路径来引用它们。一般这里存放网站的页签图标和 index.html 页面。

src 文件夹:

选择 TypeScript 时会出现 shims-tsx.d.ts 和 shims-vue.d.ts 两个文件

  • shims-tsx.d.ts,允许你以.tsx结尾的文件,在Vue项目中编写jsx代码
  • shims-vue.d.ts 主要用于 TypeScript 识别.vue 文件,Ts默认并不支持导入 vue 文件,这个文件告诉ts 导入.vue 文件都按VueConstructor<Vue>处理。

main.ts(main.js): 入口文件,类似于 main 方法,当执行完毕 npm run serve 后会执行这个文件。

App.vue:根实例组件,类似于 new Vue({}) 的写法。

router:路由文件夹。

components:组件文件夹,除过 App.vue 根组件外其他组件都在这里书写。

assets:静态资源文件夹,图片、视频等静态内容都在这里。

views: 3.x 后新引进来的文件夹,对 components 文件夹进行了更详细的区分,views是页面级组件,components是小组件,小组件可被引用在views中,一般views组件不被复用。

注意:因为创建时选择的模块不同,每次产生的文件会有所不同。 

main.js 文件详解

  1. // 这个文件是整个项目的入口文件
  2. // 引入Vue
  3. import Vue from 'vue'
  4. // 引入 App 组件,它是所有组件的父组件,对应普通Vue的那个<div id="app></div>
  5. import App from './App.vue'
  6. // 引入路由文件夹
  7. import router from './router'
  8. // 关闭 vue 的生产提示
  9. Vue.config.productionTip = false
  10. // 创建 vue 根实例对象
  11. new Vue({
  12. // 注册路由 出自于router的index.ts
  13. router,
  14. // 将 App 组件放入容器中 注册 App 组件
  15. render: h => h(App)
  16. }).$mount('#app') // 也可以写成 el:'#app'

index.html 文件详解

  1. <!DOCTYPE html>
  2. <html lang="">
  3. <head>
  4. <meta charset="utf-8">
  5. <!--针对IE浏览器的一个特殊配置,含义是让IE浏览器以最高的渲染级别渲染页面-->
  6. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  7. <!--开启移动端的理想视口-->
  8. <meta name="viewport" content="width=device-width,initial-scale=1.0">
  9. <!--配置页签图标-->
  10. <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  11. <!--配置网页标题-->
  12. <title><%= htmlWebpackPlugin.options.title %></title>
  13. </head>
  14. <body>
  15. <!--当浏览器不支持 js 时 noscript 中的元素会被渲染-->
  16. <noscript>
  17. <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
  18. </noscript>
  19. <!--容器,也是页面中我们关心的地方-->
  20. <div id="app"></div>
  21. <!-- built files will be auto injected -->
  22. </body>
  23. </html>

Xxx.vue 文件详解

.vue文件就是一个(或局部)组件。 里面包括三个部分template、js 和 css。

  1. <template>
  2. <div>
  3. <h1>我是关为,我为自己代言☺</h1>
  4. <guanwei02></guanwei02>
  5. </div>
  6. </template>
  7. <script>
  8. // 注册局部组件,在哪注册,在哪使用 在App.vue里注册的只能在App.vue里面使用
  9. import guanwei02 from './components/guanwei02.vue'
  10. export default {
  11. // 当前组件的名称
  12. name:'guanwei01',
  13. // 引入其他组件
  14. components:{
  15. guanwei02 // 这里对应 import guanwei02也和<guanwei02></guanwei02>对应
  16. }
  17. }
  18. </script>
  19. <style>
  20. </style>

vue.config.js 文件详解

  1. module.exports = {
  2. // publicPath:process.env.NODE_ENV === 'production' ? '/vue_workspac/aihuhuproject/' : '/',
  3. //基本路径
  4. publicPath: './',//默认的'/'是绝对路径,如果不确定在根路径,改成相对路径'./'
  5. // 输出文件目录
  6. outputDir: 'dist',
  7. assetsDir: 'static',
  8. indexPath: 'index.html',
  9. // eslint-loader 是否在保存的时候检查
  10. lintOnSave: true,
  11. // 生产环境是否生成 sourceMap 文件
  12. productionSourceMap: false,
  13. // css相关配置
  14. css: {
  15. // 是否使用css分离插件 ExtractTextPlugin
  16. extract: true,
  17. // 开启 CSS source maps?
  18. sourceMap: false,
  19. },
  20. // webpack-dev-server 相关配置
  21. devServer: {
  22. open: false,//open 在devServer启动且第一次构建完成时,自动用我们的系统的默认浏览器去打开要开发的网页
  23. host: '0.0.0.0',//默认是 localhost。如果你希望服务器外部可访问,指定如下 host: '0.0.0.0',设置之后之后可以访问ip地址
  24. port: 8080,//设置端口号
  25. hot: true,//hot配置是否启用模块的热替换功能,devServer的默认行为是在发现源代码被变更后,通过自动刷新整个页面来做到事实预览,开启hot后,将在不刷新整个页面的情况下通过新模块替换老模块来做到实时预览。
  26. https: false,
  27. hotOnly: false,// hot 和 hotOnly 的区别是在某些模块不支持热更新的情况下,前者会自动刷新页面,后者不会刷新页面,而是在控制台输出热更新失败
  28. proxy: {
  29. '/': {
  30. target: 'http://guanwei:8080', //目标接口域名
  31. secure: false, //false为http访问,true为https访问
  32. changeOrigin: true, //是否跨域
  33. pathRewrite: {
  34. '^/': '/' //重写接口
  35. }
  36. }
  37. }, // 设置代理
  38. before: app => { }
  39. },
  40. // 第三方插件配置
  41. pluginOptions: {
  42. // ...
  43. }
  44. };

npm run serve 命令执行完毕后脚手架做了什么?

  1. 执行 main.ts(或main.js) 文件。
  2. main.ts 中加载了 Vue、路由等依赖,引入了 App 组件,将这个组件放入 app 容器。
  3. App 组件(App.vue)引入了其他组件。
  4. 访问了 index.html 页面,显示 <div id="app"></div> 容器的内容。

VueCLI 中整合 ElementUI

安装element ui组件,在项目目录下使用一下命令安装。

npm i element-ui -S

在 main.js 中引入 element ui 功能。

  1. import Vue from "vue";
  2. import App from "./App.vue";
  3. import router from "./router";
  4. /**************引入ElementUI组件*****************/
  5. //导入ElementUI组件
  6. import ElementUI from 'element-ui';
  7. import 'element-ui/lib/theme-chalk/index.css';
  8. Vue.use(ElementUI);//设置在Vue中使用ElementUI
  9. /****************************************/
  10. Vue.config.productionTip = false;
  11. new Vue({
  12. router,
  13. render: (h) => h(App),
  14. }).$mount("#app");

VueCLI 中整合 Axios 

安装Axios,在项目目录下输入一下命令完成axios的安装。

npm install axios

在 main.js 中引入 Axios 功能。

  1. import Vue from "vue";
  2. import App from "./App.vue";
  3. import router from "./router";
  4. //导入ElementUI组件
  5. import ElementUI from 'element-ui';
  6. import 'element-ui/lib/theme-chalk/index.css';
  7. /************引入axios****************/
  8. //导入axios组件
  9. import axios from 'axios'
  10. //创建axios实例对象,并进行通用配置
  11. var axiosInstance = axios.create({
  12. //设置axios进行ajax请求的基础路径
  13. baseURL:'http://localhost:3000/',
  14. //设置请求头,指定请求为ajax请求
  15. headers:{'X-Requested-With': 'XMLHttpRequest'}
  16. });
  17. //将axios设置为Vue的原型属性
  18. Vue.prototype.$axios=axiosInstance;
  19. /***********************************/
  20. Vue.use(ElementUI);//设置在Vue中使用ElementUI
  21. Vue.config.productionTip = false;
  22. new Vue({
  23. router,
  24. render: (h) => h(App),
  25. }).$mount("#app");

注意:axios 做为 Vue 的原型属性被引入,属性名为 $axios,在 vue 视图中通过 this.$axios 来使用 axios,也可以直接通过 axios 来调用。

Vue 脚手架跨域

什么是跨域 

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议任一不同,都是跨域。在前后端分离的模式下,前后端的域名是不一致的,此时就会发生跨域访问问题。跨域出于浏览器的同源策略限制。

同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)。

如何解决跨域

处理跨域我们有多重方案可供选择:

1. 使用 ajax 的 jsonp 方案。

2. 使用 cors 方案。

3. 设置 document.domain 解决无法读取非同源网页的 Cookie 问题.

4. 跨文档通信 API:window.postMessage()。

5. Vue 脚手架中的配置方案。

其实跨域的方案有很多种,这里只罗列了5种方式,在这里我们不探讨前4种方案,有兴趣的童鞋可以下来自行了解。我们来说一说 VueCLI 的跨域处理。

VueCLI 的跨域处理

1. 配置 vue.config.js 文件

  1. const {defineConfig} = require('@vue/cli-service')
  2. module.exports = defineConfig({
  3. transpileDependencies: true,
  4. lintOnSave: false, // 关闭语法检查 如果为true要求命名规范为驼峰
  5. devServer: {
  6. proxy: {
  7. '/api': {
  8. // 后台服务器的网址,到项目名称就行 具体路径由axios请求
  9. target: 'http://guanwei:8080/guanwei_war',
  10. // 是否开启本地代理 默认true
  11. changeOrigin: true,
  12. pathRewrite: {
  13. '^/api': ''
  14. }
  15. }
  16. }
  17. }
  18. })

2. axios 中进行跨域请求

  1. // 必须以 /api开头 这样代理会被触发 guanwei/find 是具体资源名称
  2. axios.get('/api/guanwei/find')
  3. .then(function (response) {
  4. // 具体的一些操作
  5. });

网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发