当前位置:   article > 正文

Vue基础教程深入篇_深入vue

深入vue

1. 父级向子级组件传值

父组件中可以使用静态绑定传入子组件的值,也可以动态绑定传入子组件的值:

  1. <!doctype html>
  2. <html lang="zh-CH">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>父级向子级组件传值</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <App></App>
  13. </div>
  14. </body>
  15. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  16. <script>
  17. Vue.component('VBtn', {
  18. data() {
  19. return {}
  20. },
  21. template: `
  22. <button @click="clickHandler">{{ id }}</button>
  23. `,
  24. props: ['id'],
  25. methods: {
  26. clickHandler() {
  27. // 每个组件中的this指的是当前组件对象
  28. console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  29. }
  30. },
  31. created() {
  32. console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  33. }
  34. })
  35. let Vheader = {
  36. data() {
  37. return {
  38. text: '我是子组件中的数据!'
  39. }
  40. },
  41. template: `
  42. <div>
  43. {{ text }}分割线下面是来自父组件传过来的值:
  44. <hr>
  45. msg:{{ msg }}<br>
  46. post.id:{{ post.id }}<br>
  47. post.title:{{ post.title }}<br><br>
  48. <VBtn :id="post.id" @click="clickHandler"></VBtn>
  49. </div>
  50. `,
  51. // 挂载父组件属性。只要声明了父组件的属性就可以使用
  52. props: ['msg', 'post'],
  53. methods: {
  54. // 由于是VBtn调用clickHandler,所以这里的clickHandler不会被执行
  55. clickHandler() {
  56. alert(1)
  57. }
  58. },
  59. created() {
  60. console.log(this) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  61. }
  62. }
  63. let App = {
  64. data() {
  65. return {
  66. text: '我是父组件中准备传入子组件中的数据,可以使用v-bind动态绑定也可以静态绑定!',
  67. post: {
  68. id: 1,
  69. title: '我是父组件自定的属性title!'
  70. }
  71. }
  72. },
  73. template: `
  74. <div>
  75. <Vheader :msg="text" :post="post"></Vheader>
  76. </div>
  77. `,
  78. components: {
  79. Vheader: Vheader
  80. },
  81. created() {
  82. console.log(this) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  83. }
  84. }
  85. let vm = new Vue({
  86. el: '#app',
  87. data() {
  88. return {}
  89. },
  90. components: {
  91. App
  92. },
  93. created() {
  94. console.log(this) // Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
  95. }
  96. })
  97. </script>
  98. </html>

在这里插入图片描述

2. 子级向父级组件传值

这里沿用第1部分做的:

  1. <!doctype html>
  2. <html lang="zh-CH">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>子组件向父组件传值</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <App></App>
  13. </div>
  14. </body>
  15. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  16. <script>
  17. Vue.component('VBtn', {
  18. data() {
  19. return {}
  20. },
  21. template: `
  22. <button @click="clickHandler">{{ id }}</button>
  23. `,
  24. props: ['id'],
  25. methods: {
  26. clickHandler() {
  27. // 每个组件中的this指的是当前组件对象
  28. console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  29. // this.$emit('父组件声明自定义的事件', '传值')
  30. console.log('VBtn组件:', this.id)
  31. this.$emit('VheaderHandler', this.id)
  32. }
  33. },
  34. created() {
  35. console.log(this) // VueComponent {_uid: 3, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  36. },
  37. })
  38. let Vheader = {
  39. data() {
  40. return {
  41. text: '我是子组件中的数据!'
  42. }
  43. },
  44. template: `
  45. <div>
  46. {{ text }}分割线下面是来自父组件传过来的值:
  47. <hr>
  48. msg:{{ msg }}<br>
  49. post.id:{{ post.id }}<br>
  50. post.title:{{ post.title }}<br><br>
  51. <VBtn :id="post.id" @VheaderHandler="VheaderHandler"></VBtn>
  52. </div>
  53. `,
  54. // 挂载父组件属性。只要声明了父组件的属性就可以使用
  55. props: ['msg', 'post'],
  56. methods: {
  57. // 由于是VBtn调用clickHandler,所以这里的clickHandler不会被执行
  58. VheaderHandler(val) { // @VheaderHandler与其值可以不一样,但必须与子组件中的this.$emit('VheaderHandler', this.id)中的VheaderHandler一样
  59. console.log('Vheader组件:' + val)
  60. this.$emit('AppHandler', val)
  61. }
  62. },
  63. created() {
  64. console.log(this) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  65. }
  66. }
  67. let App = {
  68. data() {
  69. return {
  70. text: '我是父组件中准备传入子组件中的数据,我需要通过v-bind绑定才能使用!',
  71. post: {
  72. id: 1,
  73. title: '我是父组件自定的属性title!'
  74. }
  75. }
  76. },
  77. template: `
  78. <div>
  79. <Vheader :msg="text" :post="post" @AppHandler="app_handler"></Vheader>
  80. </div>
  81. `,
  82. components: {
  83. Vheader: Vheader
  84. },
  85. created() {
  86. console.log(this) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  87. },
  88. methods: {
  89. app_handler(val) {
  90. console.log('App组件:' + val)
  91. this.post.id = val
  92. }
  93. }
  94. }
  95. let vm = new Vue({
  96. el: '#app',
  97. data() {
  98. return {}
  99. },
  100. components: {
  101. App
  102. },
  103. created() {
  104. console.log(this) // Vue {_uid: 0, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: Vue, …}
  105. }
  106. })
  107. </script>
  108. </html>

在这里插入图片描述

3. 平行组件传值
  1. <!doctype html>
  2. <html lang="zn-CH">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>平行组件传值</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <App></App>
  13. </div>
  14. </body>
  15. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  16. <script>
  17. // Test1组件向Test2传值,Test2要声明事件:$on('事件的名字',function(){}),Test1要触发事件:$emit('Test声明的事件的名字','值')
  18. // 前提:这两个方法必须同一个实例化对象“bus”上
  19. let bus = new Vue() // 新建Vue对象作为两个方法共同绑定的实例化对象
  20. Vue.component('Test2', {
  21. data() {
  22. return {
  23. txt: '我是Test2组件!',
  24. text: ''
  25. }
  26. },
  27. template: `
  28. <div>
  29. {{ txt }}
  30. {{ text }}
  31. </div>
  32. `,
  33. created() {
  34. bus.$on('testData', (val) => {
  35. console.log(bus)
  36. console.log('传递过来的值:' + val)
  37. this.text = val
  38. })
  39. }
  40. })
  41. Vue.component('Test1', {
  42. data() {
  43. return {
  44. msg: '收到来自Test1组件的数据!'
  45. }
  46. },
  47. props: ['txt'],
  48. template: `
  49. <button @click="clickHandler">{{ txt }}</button>
  50. `,
  51. methods: {
  52. clickHandler() {
  53. console.log("bus:" + bus)
  54. bus.$emit('testData', this.msg)
  55. }
  56. }
  57. })
  58. let Vheader = {
  59. data() {
  60. return {
  61. txt: '传递'
  62. }
  63. },
  64. template: `
  65. <div class="header">
  66. <Test1 :txt="txt"></Test1>
  67. <Test2></Test2>
  68. </div>
  69. `
  70. }
  71. let App = {
  72. data() {
  73. return {}
  74. },
  75. template: `
  76. <div class="app">
  77. <Vheader></Vheader>
  78. </div>
  79. `,
  80. components: {
  81. Vheader: Vheader
  82. }
  83. }
  84. let vm = new Vue({
  85. el: '#app',
  86. data() {
  87. return {}
  88. },
  89. components: {
  90. App: App
  91. }
  92. })
  93. </script>
  94. </html>

在这里插入图片描述
在这里插入图片描述

4. Vue全家桶是什么

vue和vue-router以及vuex三者合起来是Vue的全家桶,Vue全家桶主要用来做SPA(Simple Page Application)单页面应用。

5. 为什么要使用单页面应用

传统的路由跳转,如果后端资源比较多,会导致页面出现 “白屏” 现象。让前端来做路由,在某个生命周期函数中发送 AJAX,数据驱动视图,提升用户体验。

6. 安装vue-cli脚手架

淘宝npm镜像:https://developer.aliyun.com/mirror/NPM?from=tnpm
vue-cli官网:https://cli.vuejs.org/zh/guide/

  1. # 安装cnpm
  2. $ npm install -g cnpm --registry=https://registry.npm.taobao.org
  3. # 安装vue-cli
  4. $ npm install -g @vue/cli
7. 过滤器的使用

局部过滤器:在当前组件内部使用过滤器。使用过滤器其实就是给某系数据“添油加醋”,使用的格式(伪代码):

  1. //声明
  2. filters:{
  3. '过滤器的名字':function(val,a,b){
  4. // val就是当前的数据,a和b是参数
  5. }
  6. }
  7. //使用管道符
  8. 数据 | 过滤器的名字('erics''thanlon') // a='erics',b='thanlon',管道符|左右的空格也可以删除

局部过滤器使用示例:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>过滤器</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <App/>
  13. </div>
  14. </body>
  15. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  16. <script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/moment.js"></script>
  17. <script>
  18. // 这是个局部组件,非全局组件
  19. let App = {
  20. data() {
  21. return {
  22. msg: 'Hello World!',
  23. time: new Date()
  24. }
  25. },
  26. template: `
  27. <div>
  28. {{ msg|myReverse }}
  29. {{ time | myTime('YYYY-MM-DD') }}
  30. </div>
  31. `,
  32. filters: {
  33. myReverse: function (val) {
  34. console.log(val) // Hello World!
  35. return val.split('').reverse().join('') // 'Hello World!'->['H','e',,,,]->['!','d']->'!dlroW olleH'
  36. },
  37. // 年-月-日(YYYY-MM-DD),年可以不区分大小写,但月日必须区分
  38. myTime: function (val, formatStr) {
  39. return moment(val).format(formatStr)
  40. }
  41. }
  42. }
  43. new Vue({
  44. el: '#app',
  45. data() {
  46. return {}
  47. },
  48. components: {
  49. App
  50. }
  51. })
  52. </script>
  53. </html>

在这里插入图片描述

全局过滤器:只要过滤器一创建,在任何组件中都能使用。使用的格式(伪代码):

  1. Vue.filter('过滤器的名字'function(val,a,b){})
  2. //在各个组件中都能使用
  3. 数据 | 过滤器的名字('thanlon''erics')

全局过滤器使用示例:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>过滤器</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <App/>
  13. </div>
  14. </body>
  15. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  16. <script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.27.0/moment.js"></script>
  17. <script>
  18. //全局过滤器,
  19. Vue.filter('myTime', function (val, formatStr) {
  20. return moment(val).format(formatStr);
  21. })
  22. // 这是个局部组件,非全局组件
  23. let App = {
  24. data() {
  25. return {
  26. msg: 'Hello World!',
  27. time: new Date()
  28. }
  29. },
  30. template: `
  31. <div>
  32. {{ msg|myReverse }}
  33. {{ time | myTime('YYYY-MM-DD') }}
  34. </div>
  35. `,
  36. filters: {
  37. myReverse: function (val) {
  38. console.log(val) // Hello World!
  39. return val.split('').reverse().join('') // 'Hello World!'->['H','e',,,,]->['!','d']->'!dlroW olleH'
  40. },
  41. }
  42. }
  43. new Vue({
  44. el: '#app',
  45. data() {
  46. return {}
  47. },
  48. components: {
  49. App
  50. }
  51. })
  52. </script>
  53. </html>

同样的效果:
在这里插入图片描述

过滤器是针对某一个页面的某些个操作,如将后端返回的钱数加上美元符号$或者做其它的处理,如将后端返回的很长的文本进行处理,截取指定长度的字符串,多余的字符串可以拼接上三个点。

8. 生命周期的钩子函数

开始到结束的过程就是一个生命周期,Vue生命周期的钩子函数主要有以下几种:beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、activated、deactivated、beforeDestory、destoryed。

beforeCreate:组件创建之前
created:组件创建之后
beforeMount:装载数据到DOM之前
mounted:装载数据到DOM之后
beforeUpdate:获取原始DOM
updated:获取更新之后的DOM
activated:激活当前组件(vue提供内置组件 <keep-alive></keep-alive>
deactivated:停用当前组件
beforeDestory:组件销毁之前
destoryed:组件销毁之后

生命周期钩子函数.html:(不建议使用中文命名)

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>生命周期钩子函数</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. <App></App>
  13. </div>
  14. </body>
  15. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  16. <script>
  17. let Test = {
  18. data() {
  19. return {
  20. msg: 'Erics',
  21. count: 0,
  22. timer: null,
  23. }
  24. },
  25. template: `
  26. <div id="test">
  27. <span id="box">我的名字是{{ msg }}!</span>
  28. <hr>
  29. <button @click="changeName">修改</button>
  30. <hr>
  31. {{ count }}
  32. </div>
  33. `,
  34. methods: {
  35. changeName() {
  36. this.msg = 'Kiku'
  37. document.getElementById('box').style.color = 'red'
  38. }
  39. },
  40. beforeCreate() {
  41. /**
  42. * 组件创建之前
  43. * beforeCreate获取不到数据
  44. */
  45. console.log('组件创建之前:', this.msg)
  46. },
  47. created() {
  48. /**
  49. * 组件创建之后,使用该组件就会触发以上钩子方法,created中可以操作数据、可以发送AJAX,并且可以实现数据驱动视图
  50. * 已经有数据了(DOM渲染完成之前),created只是把template创建出来,但是还没有被渲染到app组件中,更没有渲染到Vue中
  51. * Tip:90%的情况下是在created方法中获取数据
  52. * 组件创建之后才可以获取数据
  53. */
  54. console.log('组件创建之后:', this.msg)
  55. // this.msg = 'Thanlon'
  56. this.timer = setInterval(() => {
  57. this.count++
  58. }, 5000)
  59. /**
  60. *虚拟DOM:由React引出,比原生js和jquery操作DOM效率要有所提高
  61. */
  62. },
  63. beforeMount() {
  64. /**
  65. * 装载数据到DOM之前会调用
  66. */
  67. console.log('装载数据到DOM之前会调用:', document.getElementById('app'))
  68. },
  69. mounted() {
  70. /**
  71. * 这个地方可以操作DOM,装载数据到DOM之后(DOM挂载完成)会被调用,可以获取真实存在的DOM元素(标签已经被渲染了)
  72. * Tip:这里可以操作DOM;能用数据驱动改数据就不用操作DOM
  73. */
  74. console.log('装载数据到DOM之后会调用:', document.getElementById('app'))
  75. },
  76. beforeUpdate() {
  77. /**
  78. * 在更新之前调用,获取原始的DOM
  79. */
  80. console.log('在更新之前调用:')
  81. console.log(document.getElementById('app').innerHTML);
  82. },
  83. updated() {
  84. /**
  85. * 在更新之后调用,获取嘴型的DOM
  86. */
  87. console.log('在更新之后调用:')
  88. console.log(document.getElementById('app').innerHTML)
  89. },
  90. beforeDestroy() {
  91. console.log('销毁组件之前调用!')
  92. },
  93. destroyed() {
  94. console.log('销毁组件之后调用!', this.timer) // 每次创建定时器数字是不一样的
  95. // 销毁定时器,销毁和创建很消耗性能
  96. clearInterval(this.timer)
  97. },
  98. activated() {
  99. console.log('组件被激活了!')
  100. },
  101. deactivated() {
  102. console.log('组件被停用了!')
  103. }
  104. }
  105. let App = {
  106. data() {
  107. return {
  108. isShow: true
  109. }
  110. },
  111. /**
  112. template: `
  113. <div>
  114. <Test v-if="isShow"></Test>
  115. <hr>
  116. <button @click="clickHandler">改变Test组件的生死!</button>
  117. </div>
  118. `,
  119. **/
  120. // 这个组件被缓存起来,keep-alive是Vue内置的,其作用是让组件产生缓存
  121. template: `
  122. <div>
  123. <keep-alive>
  124. <Test v-if="isShow"></Test>
  125. </keep-alive>
  126. <hr>
  127. <button @click="clickHandler">改变Test组件的生死!</button>
  128. </div>
  129. `,
  130. components: {
  131. Test: Test
  132. },
  133. methods: {
  134. clickHandler() {
  135. this.isShow = !this.isShow
  136. }
  137. }
  138. }
  139. let vm = new Vue({
  140. el: '#app',
  141. data() {
  142. return {};
  143. },
  144. components: {
  145. App: App
  146. }
  147. })
  148. </script>
  149. </html>

没有使用 keep-alive 缓存组件:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
使用 keep-alive 缓存组件时:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

created 和 mounted 是比较重要的两个钩子函数!created 是在组件创建完成后触发的钩子函数,在函数中可以发起 ajax (XMLHttpRequest,XHR)、axios、fetch、$ajax 请求实现数据驱动视图。mounted 是在 DOM 装载数据之后调用,可以在这里请求数据。组件创建完成后和 DOM 装载数据之后发送获取数据的请求都是没所谓的。获取数据的过程是很快的,大部分是在组件加载之后提前准备好数据。

9. router的基本使用

router的基本使用.html:

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>router的基本使用</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. </div>
  13. </body>
  14. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  15. <script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
  16. <script>
  17. let Home = {
  18. data() {
  19. return {}
  20. },
  21. template: `
  22. <div>首页内容!</div>
  23. `
  24. }
  25. let Course = {
  26. data() {
  27. return {}
  28. },
  29. template: `
  30. <div>免费课程内容!</div>
  31. `
  32. }
  33. const router = new VueRouter({
  34. mode: 'history',
  35. //定义路由规则
  36. routes: [
  37. {
  38. path: '/',
  39. redirect: '/home'
  40. },
  41. {
  42. path: '/home',
  43. component: Home
  44. },
  45. {
  46. path: '/course',
  47. component: Course
  48. }
  49. ]
  50. })
  51. let App = {
  52. data() {
  53. return {}
  54. },
  55. // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
  56. template: `
  57. <div>
  58. <div class="header">
  59. <router-link to="/">首页</router-link>
  60. <router-link to="/course">免费课程</router-link>
  61. </div>
  62. <hr>
  63. <router-view></router-view>
  64. </div>
  65. `,
  66. components: {
  67. Home: Home
  68. }
  69. }
  70. let vm = new Vue({
  71. el: '#app',
  72. // 挂载路由对象(router对象)到Vue的实例中
  73. router: router,
  74. data() {
  75. return {}
  76. },
  77. template: `
  78. <App></App>
  79. `,
  80. components: {
  81. App: App
  82. }
  83. })
  84. </script>
  85. </html>

在这里插入图片描述
在这里插入图片描述

router-link默认被渲染成a标签,to属性会被渲染成href!

10. 命名路由和动态路由匹配

命名路由其实就是给路由命名,使用的时候直接使用路由的名字来代替路由。

命名路由.html:

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>命名路由</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. </div>
  13. </body>
  14. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  15. <script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
  16. <script>
  17. let Home = {
  18. data() {
  19. return {}
  20. },
  21. template: `
  22. <div>首页内容!</div>
  23. `
  24. }
  25. let Course = {
  26. data() {
  27. return {}
  28. },
  29. template: `
  30. <div>免费课程内容!</div>
  31. `
  32. }
  33. const router = new VueRouter({
  34. mode: 'history',
  35. //定义路由规则
  36. routes: [
  37. {
  38. path: '/',
  39. redirect: '/home'
  40. },
  41. {
  42. path: '/home',
  43. name: 'Home',
  44. component: Home
  45. },
  46. {
  47. path: '/course',
  48. name: 'Course',
  49. component: Course
  50. }
  51. ]
  52. })
  53. let App = {
  54. data() {
  55. return {}
  56. },
  57. // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
  58. template: `
  59. <div>
  60. <div class="header">
  61. <router-link :to="{name:'Home'}">首页</router-link>
  62. <router-link :to="{name:'Course'}">免费课程</router-link>
  63. </div>
  64. <hr>
  65. <router-view></router-view>
  66. </div>
  67. `,
  68. components: {
  69. Home: Home
  70. }
  71. }
  72. let vm = new Vue({
  73. el: '#app',
  74. // 挂载路由对象
  75. router: router,
  76. data() {
  77. return {}
  78. },
  79. template: `
  80. <App></App>
  81. `,
  82. components: {
  83. App: App
  84. }
  85. })
  86. </script>
  87. </html>

/user/1和/user/2加载的是同一个组件,动态路由匹配示例:

动态路由匹配.html:

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>动态路由匹配</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. </div>
  13. </body>
  14. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  15. <script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
  16. <script>
  17. let User = {
  18. data() {
  19. return {
  20. user_id: null,
  21. }
  22. },
  23. template: `
  24. <div>我是用户{{ user_id }}!</div>
  25. `,
  26. created() {
  27. /**
  28. * 当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
  29. * 只调用一次
  30. */
  31. console.log(this.$route) // 路由信息对象:{name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
  32. },
  33. watch: {
  34. '$route'(to, from) {
  35. // 对路由变化做出响应
  36. console.log('to:', to) // to: {name: "User", meta: {…}, path: "/user/2", hash: "", query: {…}, …}\
  37. console.log('from:', from) // from: {name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
  38. console.log(to.params.id)
  39. this.user_id = to.params.id
  40. // 发送AJAX
  41. }
  42. }
  43. }
  44. // 创建路由
  45. const router = new VueRouter({
  46. mode: 'history',
  47. //定义路由规则
  48. routes: [
  49. {
  50. path: '/user/:id',
  51. name: 'User',
  52. component: User
  53. },
  54. ]
  55. })
  56. let App = {
  57. data() {
  58. return {}
  59. },
  60. // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
  61. template: `
  62. <div>
  63. <div class="header">
  64. <router-link :to="{name:'User',params:{id:1}}">用户1</router-link>
  65. <router-link :to="{name:'User',params:{id:2}}">用户2</router-link>
  66. </div>
  67. <hr>
  68. <router-view></router-view>
  69. </div>
  70. `,
  71. components: {
  72. User: User
  73. }
  74. }
  75. let vm = new Vue({
  76. el: '#app',
  77. // 挂载路由对象
  78. router: router,
  79. data() {
  80. return {}
  81. },
  82. template: `
  83. <App></App>
  84. `,
  85. components: {
  86. App: App
  87. }
  88. })
  89. </script>
  90. </html>

在这里插入图片描述

watch可以用来监听路由的变化!

$.route是路由信息对象,$router是路由对象VueRouter!

11. 编程式导航

上面所有部分使用的是声明式导航:

  1. <router-link :to="{name:'User',params:{id:1}}">用户1</router-link>
  2. <router-link :to="{name:'User',params:{id:2}}">用户2</router-link>

编程式导航:

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>编程式导航</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. </div>
  13. </body>
  14. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  15. <script src="//unpkg.com/vue-router/dist/vue-router.js"></script>
  16. <script>
  17. let Home = {
  18. data() {
  19. return {}
  20. },
  21. template: `
  22. <div>我是首页</div>
  23. `
  24. }
  25. let User = {
  26. data() {
  27. return {
  28. user_id: null,
  29. }
  30. },
  31. template: `
  32. <div>
  33. <button @click="clickHandler">跳转首页</button>
  34. <span>User{{ user_id }}!</span>
  35. </div>
  36. `,
  37. created() {
  38. /**
  39. * 当使用路由参数时,例如从 /user/foo 导航到 /user/bar,原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用。
  40. * 只调用一次
  41. */
  42. console.log(this.$route) // 路由信息对象:{name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
  43. },
  44. watch: {
  45. '$route'(to, from) {
  46. // 对路由变化做出响应
  47. console.log('to:', to) // to: {name: "User", meta: {…}, path: "/user/2", hash: "", query: {…}, …}\
  48. console.log('from:', from) // from: {name: "User", meta: {…}, path: "/user/1", hash: "", query: {…}, …}
  49. console.log(to.params.id)
  50. this.user_id = to.params.id
  51. // 发送AJAX
  52. }
  53. },
  54. methods: {
  55. // 编程式导航
  56. clickHandler() {
  57. this.$router.push({
  58. name: 'Home'
  59. })
  60. }
  61. }
  62. }
  63. // 创建路由
  64. const router = new VueRouter({
  65. mode: 'history',
  66. //定义路由规则
  67. routes: [
  68. {
  69. path: '/home',
  70. name: 'Home',
  71. component: Home
  72. },
  73. {
  74. path: '/user/:id',
  75. name: 'User',
  76. component: User
  77. },
  78. ]
  79. })
  80. let App = {
  81. data() {
  82. return {}
  83. },
  84. // router-link和router-view是vue-router提供的两个全局组件,vue-router是路由组件的出口
  85. template: `
  86. <div>
  87. <div class="header">
  88. <router-link :to="{name:'User',params:{id:1}}">用户1</router-link>
  89. <router-link :to="{name:'User',params:{id:2}}">用户2</router-link>
  90. </div>
  91. <hr>
  92. <router-view></router-view>
  93. </div>
  94. `,
  95. components: {
  96. User: User
  97. }
  98. }
  99. let vm = new Vue({
  100. el: '#app',
  101. // 挂载路由对象
  102. router: router,
  103. data() {
  104. return {}
  105. },
  106. template: `
  107. <App></App>
  108. `,
  109. components: {
  110. App: App
  111. }
  112. })
  113. </script>
  114. </html>

在这里插入图片描述
在这里插入图片描述

12. refs属性的使用

refs属性可以用来获取标签原生的DOM对象和组件实例,需要在mounted函数中获取。

  1. <!doctype html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>refs属性的使用</title>
  9. </head>
  10. <body>
  11. <div id="app">
  12. </div>
  13. </body>
  14. <script src="//cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
  15. <script>
  16. Vue.component('Test', {
  17. data() {
  18. return {}
  19. },
  20. template: `
  21. <div>我是测试组件1!</div>
  22. `
  23. })
  24. Vue.component('Test2', {
  25. data() {
  26. return {}
  27. },
  28. template: `
  29. <div>我是测试组件2!</div>
  30. `
  31. })
  32. let App = {
  33. data() {
  34. return {}
  35. },
  36. template: `
  37. <div>
  38. <input type="text" ref="input">
  39. <Test ref="abc"></Test>
  40. <Test2 ref="def"></Test2>
  41. </div>
  42. `,
  43. mounted() {
  44. console.log(this.$refs.input) // 获取原始DOM对象:<input type="text">
  45. console.log(this.$refs) // {input: input}...可以展开
  46. this.$refs.input.focus()
  47. console.log(this) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  48. console.log(this.$root) // VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  49. console.log(this.$refs.abc) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  50. console.log(this.$refs.parent) // undefined
  51. console.log(this.$refs.root) // undefined
  52. console.log(this.$children[0]) // VueComponent {_uid: 2, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
  53. }
  54. }
  55. let vm = new Vue({
  56. el: '#app',
  57. data() {
  58. return {}
  59. },
  60. template: `
  61. <App></App>
  62. `,
  63. components: {
  64. App
  65. }
  66. })
  67. </script>
  68. </html>

在这里插入图片描述

13. 模块化初探索

使用node来运行模块化的JavaScript程序:

test.js:

  1. let person = {
  2. name: 'erics'
  3. }
  4. module.exports = person

index.js:

  1. let person = require('./test')
  2. console.log(person)
  3. console.log(person.name)

可以使用 node index.js 命令来运行,

  1. $ node index.js
  2. { name: 'erics' }
  3. erics

使用webpack打包:

module.js:

  1. let person = {
  2. name: 'erics',
  3. func: function () {
  4. alert('success!')
  5. }
  6. }
  7. export default person;

main.js:

  1. import person from './module'
  2. console.log(person.func())

使用webpack进行打包:

  1. $ sudo webpack ./main.js -o ./bundle.js
  2. Hash: b7b9dbe6291ed213470d
  3. Version: webpack 4.44.1
  4. Time: 168ms
  5. Built at: 2020/08/21 下午1:52:26
  6. Asset Size Chunks Chunk Names
  7. bundle.js 1 KiB 0 [emitted] main
  8. Entrypoint main = bundle.js
  9. [0] ./main.js + 1 modules 170 bytes {0} [built]
  10. | ./main.js 56 bytes [built]
  11. | ./module.js 114 bytes [built]

打包完成后当前目录中多了一个bundle.js文件,这就是打包后的文件。在index.html中只需要引入它:

index.html:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>Document</title>
  9. </head>
  10. <body>
  11. </body>
  12. <script src="bundle.js"></script>
  13. </html>

main.js和module.js里面的代码成功被执行:
在这里插入图片描述
可以抛出多个变量,修改model.js和main.js重新打包,

module.js:

  1. let person = {
  2. name: 'erics',
  3. func: function () {
  4. alert('success!')
  5. }
  6. }
  7. let name = 23
  8. // 可以抛出多个变量
  9. export {name}
  10. export let nowYear = 2020
  11. export default person;

main.js:

  1. import * as a from './module'
  2. console.log(a)

在这里插入图片描述
当然可以使用a.xxx来执行函数或者获取变量。

webpack依赖于node.js!

14. Vue的模块化初探索

可以把模块化应用在Vue上,

App.js:

  1. let App = {
  2. template: `
  3. <div>我是App组件!</div>
  4. `
  5. }
  6. export default App;

main.js:

  1. import Vue from './vue'
  2. import App from './App'
  3. let vm = new Vue({
  4. el: '#app',
  5. template: `
  6. <App></App>
  7. `,
  8. components: {
  9. App
  10. }
  11. })

index.html:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>Document</title>
  9. </head>
  10. <body>
  11. <div id="app"></div>
  12. </body>
  13. <script src="./bundle.js"></script>
  14. </html>

使用webpack命令打包:webpack main.js -o bundle.js,然后可以正常访问 index.html

15. webpack的使用

很明显上面的例子中每次更新 JavaScript 代码都会重新打包,这是很繁琐的。实际上,通过设置完全可以自动打包,实时编译。首先需要通过 npm -init --yes 命令来创建配置文件 package.json

  1. {
  2. "name": "webpack_use",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "main.js",
  6. "scripts": {
  7. "test": "echo \"Error: no test specified\" && exit 1"
  8. },
  9. "keywords": [],
  10. "author": "",
  11. "license": "ISC"
  12. }

接下来通过 $ cnpm i webpack -D 下载 webpack

可以指定webpack的版本:$ cnpm i webpack@3.12.0 -D

下载完成后配置文件 package.json 中发生了变化:

  1. "devDependencies": {
  2. "webpack": "^4.44.1"
  3. }

devDependencies 指的是开发环境依赖。可以对 package.json 进行修改,使用 npm 命令 $ npm run dev 来替代 $ webpack ./main.js -o ./bundle.js 打包文件。所以,还需要修改配置文件:

  1. "scripts": {
  2. "dev": "webpack ./main.js ./bundle.js"
  3. },

还可以进行改进,修改 package.json :

  1. "scripts": {
  2. "dev": "webpack"
  3. },

我们想要只使用 webpack 命令来打包,可以在项目中创建一个 webpack 默认的配置文件 webpack.config.js,该配置文件写的都是 nodejs 代码:

  1. module.exports = {
  2. entry: {
  3. 'main': './main.js'
  4. },
  5. output: {
  6. 'filename': './bundle.js'
  7. }
  8. }

使用 $npm run dev 会优先找配置文件 webpack.config.js,找到入口 main.js,打包输出 bundle.js。为了实现 监听代码的改动自动编译,需要加上 watch:true

  1. module.exports = {
  2. entry: {
  3. 'main': './main.js'
  4. },
  5. output: {
  6. 'filename': './bundle.js'
  7. },
  8. watch: true
  9. }

开发环境中需要有监听代码自动编译功能,生产环境不需要,

webpack.dev.config.js:

  1. module.exports = {
  2. entry: {
  3. 'main': './main.js'
  4. },
  5. output: {
  6. 'filename': './bundle.js'
  7. },
  8. watch: true
  9. }

webpack.pro.config.js:

  1. module.exports = {
  2. entry: {
  3. 'main': './main.js'
  4. },
  5. output: {
  6. 'filename': './bundle.js'
  7. }
  8. }

package.json:

  1. {
  2. "name": "webpack_use",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "main.js",
  6. "scripts": {
  7. "dev": "webpack --config ./webpack.dev.config.js",
  8. "build": "webpack --config ./webpack.pro.config.js"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "devDependencies": {
  14. "webpack": "^4.44.1",
  15. "webpack-cli": "^3.3.12"
  16. }
  17. }

如果是新版本的 webpack,可以这样配置,

webpack.pro.config.js:

  1. module.exports = {
  2. // entry: './main.js',
  3. entry: {
  4. 'main': './main.js'
  5. },
  6. output: {
  7. 'filename': './bundle.js'
  8. },
  9. watch: true,
  10. mode: 'development'
  11. }

package.json:

  1. {
  2. "name": "webpack_use",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "main.js",
  6. "scripts": {
  7. "dev": "webpack --mode development",
  8. "build": "webpack --mode production"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "devDependencies": {
  14. "webpack": "^4.44.1",
  15. "webpack-cli": "^3.3.12"
  16. }
  17. }
16. webpack中loader的使用

可以把css直接打包到js文件中,不需要再html文件中再引用。新建 index.css 文件,在里面写好样式,然后导入到 main.js 中,

index.css:

  1. body{
  2. background: rebeccapurple;
  3. }

main.js:

  1. import Vue from './vue'
  2. import App from './App'
  3. import './index.css'
  4. let vm = new Vue({
  5. el: '#app',
  6. template: `
  7. <App></App>
  8. `,
  9. components: {
  10. App
  11. }
  12. })

但是会报错:

  1. ERROR in ./index.css 1:4
  2. Module parse failed: Unexpected token (1:4)
  3. You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
  4. > body{
  5. | background: rebeccapurple;
  6. | }
  7. @ ./main.js 3:0-20

在组件中引入css,需要用到css-loader和style-loader, css-loader是用来解析css文件,style-loader是用来解析style标签的。所以需要下载并配置它们:$ cnpm i css-loader style-loader -D

webpack.config.js:

  1. module.exports = {
  2. // entry: './main.js',
  3. entry: {
  4. 'main': './main.js'
  5. },
  6. output: {
  7. 'filename': './bundle.js'
  8. },
  9. watch: true,
  10. mode: 'development',
  11. module: {
  12. rules: [
  13. {
  14. /**
  15. * 遇到后缀是css的文件,webpack首先用css-loader加载器去解析这个文件
  16. * 最后计算完的css,将会使用style-loader生成一个内容为最终解释完的css代码的style标签,放在head标签里
  17. * webpack在打包国城中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件
  18. */
  19. test: /\.css$/, // 后缀是css的文件
  20. loader: 'style-loader!css-loader', // 先去使用css-loader解析css文件再使用style-loader生成style标签(link)插入head标签中
  21. }
  22. ]
  23. }
  24. }

这个时候css就会被加入到html中。

17. webpack中plugin的使用

一般也会把 index.html 文件自动生成到 dist 文件中,所以需要使用到 html-webpack-plugin 插件。安装该插件:$ cnpm i html-webpack-plugin -D,指定版本需要加上@跟版本号。另外一个命令是 $ cnpm i html-webpack-plugin --save-dev。还需要在 webpack.config.js 进行配置:

  1. const path = require('path')
  2. // 导入模块
  3. const HtmlWebpackPlugin = require('html-webpack-plugin')
  4. module.exports = {
  5. // entry: './main.js',
  6. entry: {
  7. // 可以有多个入口,也可以有一个,如果有一个默认从这个入口开始分析
  8. 'main': './src/main.js'
  9. },
  10. output: {
  11. // 指定产出目录
  12. path: path.resolve('./dist'), // 相对转绝对路径,dist也可以改成static,webpack默认使用dist
  13. 'filename': 'build.js'
  14. },
  15. watch: true, // 文件监视改动,自动产生build.js
  16. mode: 'development',
  17. module: {
  18. rules: [
  19. {
  20. /**
  21. * 遇到后缀是css的文件,webpack首先用css-loader加载器去解析这个文件
  22. * 最后计算完的css,将会使用style-loader生成一个内容为最终解释完的css代码的style标签,放在head标签里
  23. * webpack在打包国城中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件
  24. */
  25. test: /\.css$/, // 后缀是css的文件
  26. use: ["style-loader", 'css-loader',], // 先去使用css-loader解析css文件再使用style-loader生成style标签(link)插入head标签中
  27. }
  28. ]
  29. },
  30. // 添加插件
  31. plugins: [
  32. new HtmlWebpackPlugin({
  33. // 插件的执行运行与元素索引有关
  34. template: './src/index.html', //参照物
  35. })
  36. ]
  37. }

生成之前的项目目录结构:
在这里插入图片描述
执行 $ npm run dev 执行生成之后的目录结构:
在这里插入图片描述

index.html:

  1. <!doctype html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport"
  6. content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  7. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  8. <title>webpack中plugin的使用</title>
  9. </head>
  10. <body>
  11. <div id="app"></div>
  12. <script src="build.js"></script>
  13. </body>
  14. <!--下面是自己写的,也可以不要-->
  15. <script src="dist/build.js"></script>
  16. </html>
18. 单文件的使用

使用 $ cnpm i vue-loader vue-template-compiler -D 下载用于解析 Vue文件的包 vue-loadervue-template-compiler。创建 App.vue 文件:

  1. <!--组件的模板结构-->
  2. <template>
  3. <div>
  4. App组件
  5. </div>
  6. </template>
  7. <!--组件的业务逻辑-->
  8. <script>
  9. export default {
  10. name:'App',
  11. data() {
  12. return {
  13. text: 'Hello fingle file...'
  14. }
  15. }
  16. }
  17. </script>
  18. <!--组件的样式-->
  19. <style>
  20. body {
  21. background-color: rebeccapurple;
  22. }
  23. </style>

需要在 webpack.config.js 中进行配置:

  1. const path = require('path')
  2. // 导入模块
  3. const HtmlWebpackPlugin = require('html-webpack-plugin')
  4. const VueLoaderPlugin = require('vue-loader/lib/plugin');
  5. module.exports = {
  6. // entry: './main.js',
  7. entry: {
  8. // 可以有多个入口,也可以有一个,如果有一个默认从这个入口开始分析
  9. 'main': './src/main.js'
  10. },
  11. output: {
  12. // 指定产出目录
  13. path: path.resolve('./dist'), // 相对转绝对路径,dist也可以改成static,webpack默认使用dist
  14. 'filename': 'build.js'
  15. },
  16. watch: true, // 文件监视改动,自动产生build.js
  17. mode: 'development',
  18. module: { // 这个节点用于配置所有的第三方模块加载器
  19. rules: [
  20. {
  21. /**
  22. * 遇到后缀是css的文件,webpack首先用css-loader加载器去解析这个文件
  23. * 最后计算完的css,将会使用style-loader生成一个内容为最终解释完的css代码的style标签,放在head标签里
  24. * webpack在打包国城中,遇到后缀为css的文件,就会使用style-loader和css-loader去加载这个文件
  25. */
  26. test: /\.css$/, // 后缀是css的文件
  27. use: ["style-loader", 'css-loader',], // 先去使用css-loader解析css文件再使用style-loader生成style标签(link)插入head标签中
  28. },
  29. {
  30. test: /\.vue$/,
  31. use: 'vue-loader'
  32. }
  33. ]
  34. },
  35. // 添加插件
  36. plugins: [
  37. new HtmlWebpackPlugin({
  38. // 插件的执行运行与元素索引有关
  39. template: './index.html', //参照物
  40. }),
  41. new VueLoaderPlugin()
  42. ]
  43. }

还要记得修改 main.js:

  1. import Vue from './vue'
  2. import App from './App.vue'
  3. import './index.css'
  4. let vm = new Vue({
  5. el: '#app',
  6. template: `<App></App>`,
  7. components: {
  8. App
  9. }
  10. })

执行 $ npm run dev 命令正常打包即可!

19. 单页面SPA应用

使用 $ cnpm i vue vue-router -S 安装 vuevue-router 模块,-S 表示当前项目依赖,查看 package.json:

  1. {
  2. "name": "webpack_use",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "src/main.js",
  6. "scripts": {
  7. "dev": "webpack --mode development",
  8. "build": "webpack --mode production"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "devDependencies": {
  14. "css-loader": "^4.2.1",
  15. "html-webpack-plugin": "^4.3.0",
  16. "style-loader": "^1.2.1",
  17. "vue-loader": "^15.9.3",
  18. "vue-template-compiler": "^2.6.12",
  19. "webpack": "^4.44.1",
  20. "webpack-cli": "^3.3.12"
  21. },
  22. "dependencies": {
  23. "vue": "^2.6.12",
  24. "vue-router": "^3.4.3"
  25. }
  26. }

配置路由:main.js

  1. import Vue from './vue'
  2. import App from './App.vue'
  3. import './index.css'
  4. import VueRouter from 'vue-router'
  5. import Home from './components/Home/Home'
  6. import Course from './components/Course/Course'
  7. //创建路由对象
  8. const router = new VueRouter({
  9. // 配置路由信息
  10. routers: [
  11. {
  12. path: '/',
  13. name: 'Home',
  14. component: Home
  15. },
  16. {
  17. path: '/course',
  18. name: 'Course',
  19. component: Course
  20. },
  21. ]
  22. })
  23. let vm = new Vue({
  24. el: '#app',
  25. router: router,
  26. template: `
  27. <App></App>`,
  28. components: {
  29. App
  30. }
  31. })

常用配置相关参数:

  1. --open:自动打开浏览器
  2. --hot:热更新,不在刷新的情况下替换css样式
  3. --inline:自动刷新
  4. --port 9000:指定端口
  5. --process:显示编译进度

希望可以在服务器上运行,下载模块:$ cnpm i webpack-dev-server --save-dev,查看 package.json:

  1. {
  2. "name": "webpack_use",
  3. "version": "1.0.0",
  4. "description": "",
  5. "main": "src/main.js",
  6. "scripts": {
  7. "dev": "webpack-dev-server --open --hot --inline --config ./webpack.config.js",
  8. "build": "webpack --mode production"
  9. },
  10. "keywords": [],
  11. "author": "",
  12. "license": "ISC",
  13. "devDependencies": {
  14. "css-loader": "^4.2.1",
  15. "html-webpack-plugin": "^4.3.0",
  16. "style-loader": "^1.2.1",
  17. "vue-loader": "^15.9.3",
  18. "vue-template-compiler": "^2.6.12",
  19. "webpack": "^4.44.1",
  20. "webpack-cli": "^3.3.12",
  21. "webpack-dev-server": "^3.11.0"
  22. },
  23. "dependencies": {
  24. "vue": "^2.6.12",
  25. "vue-router": "^3.4.3"
  26. }
  27. }

然后执行 $ npm run dev,自动打开了浏览器但是编译脚本报错:
在这里插入图片描述
在这里插入图片描述
找不到模块,Course.vue 和 Home.vue,排查后发现之前声明组件的时候 Home.vueCourse.vue 书写有误,修改 main.js:

  1. import Vue from './vue'
  2. // 一定要以vue结尾
  3. import App from './App.vue'
  4. import './index.css'
  5. import VueRouter from 'vue-router'
  6. // 如果基于模块化机制:Vue.use(VueRouter)
  7. // 声明组件
  8. import Home from './components/Home/Home.vue'
  9. import Course from './components/Course/Course.vue'
  10. //创建路由对象
  11. const router = new VueRouter({
  12. // 配置路由信息
  13. routers: [
  14. {
  15. path: '/',
  16. name: 'Home',
  17. component: Home
  18. },
  19. {
  20. path: '/course',
  21. name: 'Course',
  22. component: Course
  23. },
  24. ]
  25. })
  26. let vm = new Vue({
  27. el: '#app',
  28. router: router,
  29. template: `
  30. <App></App>
  31. `,
  32. components: {
  33. App
  34. }
  35. })

这个时候就可以正常编译了,编译后遇到下面的问题:
在这里插入图片描述
在这里插入图片描述
需要在 main.js 中加上 Vue.use(VueRouter)

  1. import Vue from './vue'
  2. // 一定要以vue结尾
  3. import App from './App.vue'
  4. import './index.css'
  5. import VueRouter from 'vue-router'
  6. // 基于模块化机制
  7. Vue.use(VueRouter)
  8. // 声明组件
  9. import Home from './components/Home/Home.vue'
  10. import Course from './components/Course/Course.vue'
  11. //创建路由对象
  12. const router = new VueRouter({
  13. // 配置路由信息
  14. routers: [
  15. {
  16. path: '/',
  17. name: 'Home',
  18. component: Home
  19. },
  20. {
  21. path: '/course',
  22. name: 'Course',
  23. component: Course
  24. },
  25. ]
  26. })
  27. let vm = new Vue({
  28. el: '#app',
  29. router: router,
  30. template: `<App></App>`,
  31. components: {
  32. App
  33. }
  34. })

这里可以把 main.js 中的Vue的部分修改为:

  1. let vm = new Vue({
  2. el: '#app',
  3. router: router,
  4. render: c => c(App)
  5. // template: `<App></App>`,
  6. // components: {
  7. // App
  8. // }
  9. })

在这里插入图片描述
在这里插入图片描述
Githubhttps://github.com/ThanlonSmith/SPA-Vue

20. css中scoped的使用

scoped可以使当前样式只在当前组件生效,如,

Course.vue:

  1. <template>
  2. <div>
  3. 课程列表!
  4. </div>
  5. </template>
  6. <!--组件的业务逻辑-->
  7. <script>
  8. export default {
  9. name: 'Course',
  10. data() {
  11. return {}
  12. },
  13. }
  14. </script>
  15. <!--组件的样式-->
  16. <style scoped>
  17. * {
  18. color: orange;
  19. }
  20. </style>

Home.vue:

  1. <template>
  2. <div>
  3. 首页!
  4. </div>
  5. </template>
  6. <!--组件的业务逻辑-->
  7. <script>
  8. export default {
  9. name: 'Home',
  10. data() {
  11. return {}
  12. },
  13. }
  14. </script>
  15. <!--组件的样式-->
  16. <style scoped>
  17. *{
  18. color: red;
  19. }
  20. </style>

在这里插入图片描述
在这里插入图片描述

class重复也是没有关系的!

21. vue-cli的使用

可使用的模块有:

  • webpack:一个功能齐全的 webpack + vue-loader 设置,具有热重载、linting、测试和css提取功能
  • webpack-simple:一个简单的 Webpack + vue-loader 设置,用于快速设计原型
  • browserify:全功能 browserify + vueify 设置,具有热重载,linting和单元测试功能
  • browserify-simple:一个简单的 browserify + vueify 设置,用于快速原型设计
  • pwa:基于 webpack 模板的 vue-cli 的 pwa 模板
  • simple:单个 html 文件中最简单的 Vue 设置
  • progress:滚动

使用脚手架创建一个基于 webpack-simple 模块的项目:

  1. $ vue init webpack-simple my-project
  2. ? Project name my-project
  3. ? Project description A Vue.js project
  4. ? Author erics1996 <erics1996@yeah.net>
  5. ? License MIT
  6. ? Use sass? No

进入目录,安装需要的相关依赖包:

  1. $ cd my-project
  2. $ cnpm install
  3. $ npm run dev

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
使用 $ cnpm i vue-router 下载路由,可以在src目录下创建router文件夹和index.js用来写路由相关信息:
在这里插入图片描述
将路由对象VueRouter 挂在到 Vue 实例,main.js:

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from './router/index.js' // 可以不用加js后缀,路由相关的信息在index.js中写
  4. new Vue({
  5. router,
  6. el: '#app',
  7. render: h => h(App)
  8. })

创建router目录用于存放路由相关的信息,创建componets用来存放组件:
在这里插入图片描述
index.js:

  1. import Vue from 'vue'
  2. import VueRouter from 'vue-router'
  3. import Home from "../components/Home/Home";
  4. import Course from "../components/Course/Course";
  5. Vue.use(VueRouter) // use相当于挂在父类
  6. const router = new VueRouter({
  7. // 配置路由信息
  8. routes: [ // 这里不要写错了
  9. {
  10. path: '/',
  11. redirect: '/home'
  12. },
  13. {
  14. path: '/home',
  15. name: 'Home',
  16. component: Home
  17. },
  18. {
  19. path: '/course',
  20. name: 'Course',
  21. component: Course
  22. },
  23. ]
  24. })
  25. export default router

Home.vue:

  1. <template>
  2. <div>我是首页!</div>
  3. </template>
  4. <script>
  5. export default {
  6. name: 'Home',
  7. data() {
  8. return {}
  9. },
  10. }
  11. </script>
  12. <style></style>

Course.vue:

  1. <template>
  2. <div>我是课程列表页面!</div>
  3. </template>
  4. <script>
  5. export default {
  6. name: 'Course',
  7. data() {
  8. return {}
  9. },
  10. }
  11. </script>
  12. <style></style>

App.vue:

  1. <template>
  2. <!-- <div id="app">-->
  3. <!-- <img src="./assets/logo.png">-->
  4. <!-- <h1>{{ msg }}</h1>-->
  5. <!-- <h2>Essential Links</h2>-->
  6. <!-- <ul>-->
  7. <!-- <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>-->
  8. <!-- <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>-->
  9. <!-- <li><a href="https://chat.vuejs.org" target="_blank">Community Chat</a></li>-->
  10. <!-- <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>-->
  11. <!-- </ul>-->
  12. <!-- <h2>Ecosystem</h2>-->
  13. <!-- <ul>-->
  14. <!-- <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>-->
  15. <!-- <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>-->
  16. <!-- <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>-->
  17. <!-- <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>-->
  18. <!-- </ul>-->
  19. <!-- </div>-->
  20. <div id="app">
  21. <img src="./assets/logo.png">
  22. <h4>{{ msg }}</h4>
  23. <router-link :to="{name:'Home'}">首页</router-link>
  24. <router-link :to="{name:'Course'}">课程</router-link>
  25. <router-view></router-view>
  26. </div>
  27. </template>
  28. <script>
  29. export default {
  30. name: 'app',
  31. data() {
  32. return {
  33. msg: '基于webpack-simple模板构建!'
  34. }
  35. }
  36. }
  37. </script>
  38. <style></style>

在这里插入图片描述
在这里插入图片描述
使用 webpack 模板来创建一个工程,

在这里插入图片描述
在这里插入图片描述
构建好的**工程目录结构:
在这里插入图片描述
同样使用 $ npm run dev 命令来运行:
在这里插入图片描述
默认找 index.js,可以不写后缀:

在这里插入图片描述
Vue.config.productionTip = false 的意思是生产环境不需要控制台有提示,@符号默认是 src 路径。
在这里插入图片描述

在这里插入图片描述

22. element-ui的使用

使用 $ cnpm i element-ui -S 安装 element-ui,使用 $ cnpm i 安装 element-ui 依赖的包,使用 element-ui 来布局 App.vue:

  1. <template>
  2. <div id="app">
  3. <el-container>
  4. <el-header>
  5. <router-link :to="{name:'Home'}">首页</router-link>
  6. <router-link :to="{name:'Course',query:{userid:1}}">免费课程</router-link>
  7. </el-header>
  8. <el-main>
  9. <router-view/>
  10. </el-main>
  11. </el-container>
  12. </div>
  13. </template>
  14. <script>
  15. export default {
  16. name: 'App'
  17. }
  18. </script>
  19. <style>
  20. #app {
  21. font-family: 'Avenir', Helvetica, Arial, sans-serif;
  22. -webkit-font-smoothing: antialiased;
  23. -moz-osx-font-smoothing: grayscale;
  24. text-align: center;
  25. color: #2c3e50;
  26. margin-top: 60px;
  27. }
  28. </style>

main.js:

  1. // The Vue build version to load with the `import` command
  2. // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
  3. import Vue from 'vue'
  4. import App from './App'
  5. import router from './router' // 默认找index.js
  6. import ElementUI from 'element-ui'
  7. import 'element-ui/lib/theme-chalk/index.css'
  8. import '../static/global/index.css'
  9. Vue.config.productionTip = false // 生产环境不需要控制台有提示
  10. Vue.use(ElementUI)
  11. /* eslint-disable no-new */
  12. new Vue({
  13. el: '#app',
  14. router,
  15. components: {App},
  16. template: '<App/>'
  17. })

在这里插入图片描述
在这里插入图片描述

分享一个好用的Python学习网站https://pythoneers.cn/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/69732
推荐阅读
相关标签
  

闽ICP备14008679号