VUE

vue2,经典版本,现在绝大部分的企业项目都是vue2

vue3,新版本 ,趋势

VUE初体验

基于vue.js框架来编写项目需要以下几个步骤:

  • 导入vue.js包(CDN)
  1. <!-- 开发环境版本,包含了有帮助的命令行警告 -->
  2. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  3. <!-- 生产环境版本,优化了尺寸和速度 -->
  4. <script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
  5. # 当然,也可以将文件下载下来再通过本地导入。
  • 应用
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <!-- 1.引入vue.js文件 -->
  7. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  8. </head>
  9. <body>
  10. <!-- 2.指定区域,该区域的内容希望由vue.js来接管。 -->
  11. <div id="app">
  12. <h1>欢迎学习Vue.js</h1>
  13. <div>我叫{{name}},微信{{wechat}}</div> <!-- {{}}会去vue对象的data属性里面找值-->
  14. <input type="button" value="点我" v-on:click="clickMe"> <!-- v-on:click点击事件 当点击的时候执行vue对象里的clickMe函数-->
  15. </div>
  16. <script>
  17. // 3.创建Vue对象,并关联指定HTML区域。
  18. var app = new Vue({
  19. el: '#app',
  20. data: {
  21. name: '123',
  22. wechat: '123888'
  23. },
  24. methods: {
  25. clickMe: function () {
  26. // 获取值this.name
  27. // 修改值this.name = "xx"
  28. this.name = "455";
  29. this.wechat = "455666";
  30. }
  31. }
  32. })
  33. </script>
  34. </body>
  35. </html>

vue常见指令

想要使用vue.js来进行开发,就必须学会vue.js中提供的指令,明白每个指令是什么意思,才能更灵活的让他去显示我们想要的效果。

插值表达式

一般在显示文本内容的标签中使用。就是将js中的值显示在html标签中

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <div>我叫{{name}},我喜欢{{hobby}},邮箱:{{dataInfo.email}}</div>
  11. <ul>
  12. <li>{{'456'}}</li> <!--{{}}里面可以引用vue中的值,也可以直接写一些值-->
  13. <li>{{'456' + "土鳖"}}</li>
  14. <li>{{ base + 1 + 1 }}</li>
  15. <li>{{ 1===1 ?"456":"789"}}</li> <!--1===1条件成立就是456 不成立就是789 -->
  16. </ul>
  17. <ul>
  18. <li>{{ condition?"12":"34"}}</li> <!--condition的值是用的vue对象里的值 -->
  19. </ul>
  20. <input type="button" value="点我" v-on:click="clickMe">
  21. </div>
  22. <script>
  23. var app = new Vue({
  24. el: '#app',
  25. data: {
  26. name: '123',
  27. hobby: '篮球',
  28. dataInfo: {
  29. id: 1,
  30. email: "xxx.com"
  31. },
  32. condition: false,
  33. base: 1
  34. },
  35. methods: {
  36. clickMe: function () {
  37. this.name = "小马哥";
  38. this.condition = true;
  39. this.dataInfo.email = "xmg@live.com";
  40. this.base += 100;
  41. }
  42. }
  43. })
  44. </script>
  45. </body>
  46. </html>

v-bind

一般用于对标签中的属性进行操作。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. .ig {
  9. border: 2px solid red;
  10. }
  11. </style>
  12. </head>
  13. <body>
  14. <div id="app">
  15. <img src='xx.png' class='c1' />
  16. <img alt="" v-bind:src="imageUrl" v-bind:class="cls"> <!--v-bind:src对应的imageUrl会去vue对象中找imageUrl然后复制过来 -->
  17. </div>
  18. <script>
  19. var app = new Vue({
  20. el: '#app',
  21. data: {
  22. imageUrl: 'https://hcdn2.luffycity.com/media/frontend/public_class/PY1@2x_1566529821.1110113.png',
  23. cls: "ig",
  24. }
  25. })
  26. </script>
  27. </body>
  28. </html>
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. .ig {
  9. border: 2px solid red;
  10. }
  11. .info {
  12. color: red;
  13. }
  14. .danger {
  15. font-size: 10px;
  16. }
  17. </style>
  18. </head>
  19. <body>
  20. <div id="app">
  21. <img src='xx.png' class='c1'/>
  22. <img alt="" v-bind:src="imageUrl" v-bind:class="cls">
  23. <!--内部会判断v1和v2的值,值也是去vue对象中找,只会找值为True的并赋值给class -->
  24. <h1 v-bind:class="{info:v1,danger:v2}">你好呀111</h1>
  25. <!--clsDict也是去vue对象中找,会找值为True的将键放到此处 -->
  26. <h1 v-bind:class="clsDict">你好呀</h1>
  27. <!--会将vue对象的data对象中的a1 和 a2的值放到此处 -->
  28. <h2 v-bind:class="[a1,a2]"></h2>
  29. <!--条件成立是a1,不成立是‘y’,然后还有一个a1-->
  30. <h2 v-bind:class="[1===1?a1:'y',a2]">111</h2>
  31. <!--clr会去vue data对象中去找,size也是-->
  32. <h3 v-bind:style="{ color:clr,fontSize:size+'px'}">222</h3>
  33. <h3 style="color: red;font-size: 19px">333</h3>
  34. <!--给input添加一个点击事件 当点击的时候执行vue data 属性里的clickme -->
  35. <input type="button" value="点我" v-on:click="clickMe">
  36. </div>
  37. <script>
  38. var app = new Vue({
  39. el: '#app',
  40. data: {
  41. imageUrl: 'https://hcdn2.luffycity.com/media/frontend/public_class/PY1@2x_1566529821.1110113.png',
  42. cls: "ig",
  43. v1: true,
  44. v2: true,
  45. clsDict: {
  46. info: false,
  47. danger: false
  48. },
  49. a1: "info",
  50. a2: "danger",
  51. clr: "red",
  52. size: "19",
  53. },
  54. methods:{
  55. clickMe:function () {
  56. this.v1 = false;
  57. }
  58. }
  59. })
  60. </script>
  61. </body>
  62. </html>

v-bind注意:

  • 简写的格式::属性名=xxx,例如:
    1. <h1 v-bind:class="v1"></h1>
    2. <h1 :class="v1"></h1>
    3. <img :src="xx" />
  • v-bind属于单向绑定( JS修改->HTML修改 )。

v-model

一般用于在交互的表中中使用,例如:input、select、textarea等。【双向绑定】

JS修改->HTML修改

HTML修改 -> JS修改

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <div>
  11. 用户名:<input type="text" v-model="user">
  12. </div>
  13. <div>
  14. 密码:<input type="password" v-model="pwd">
  15. </div>
  16. <input type="button" value="登录" v-on:click="clickMe"/>
  17. <input type="button" value="重置" v-on:click="resetForm"/>
  18. </div>
  19. <script>
  20. var app = new Vue({
  21. el: '#app',
  22. data: {
  23. user: "",
  24. pwd: "",
  25. },
  26. methods: {
  27. clickMe: function () {
  28. console.log(this.user, this.pwd)
  29. },
  30. resetForm: function () {
  31. this.user = "";
  32. this.pwd = "";
  33. }
  34. }
  35. })
  36. </script>
  37. </body>
  38. </html>

更多标签实例

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <div>
  11. 用户名:<input type="text" v-model="user">
  12. </div>
  13. <div>
  14. 密码:<input type="password" v-model="pwd">
  15. </div>
  16. <div>
  17. 性别:
  18. <input type="radio" v-model="sex" value="1">
  19. <input type="radio" v-model="sex" value="2">
  20. </div>
  21. <div>
  22. 爱好:
  23. <input type="checkbox" v-model="hobby" value="11">篮球
  24. <input type="checkbox" v-model="hobby" value="22">足球
  25. <input type="checkbox" v-model="hobby" value="33">评判求
  26. </div>
  27. <div>
  28. 城市:
  29. <select v-model="city">
  30. <option value="sh">上海</option>
  31. <option value="bj">北京</option>
  32. <option value="sz">深圳</option>
  33. </select>
  34. </div>
  35. <div>
  36. 擅长领域:
  37. <select v-model="company" multiple>
  38. <option value="11">技术</option>
  39. <option value="22">销售</option>
  40. <option value="33">运营</option>
  41. </select>
  42. </div>
  43. <div>
  44. 其他:<textarea v-model="more"></textarea>
  45. </div>
  46. <input type="button" value="注 册" v-on:click="clickMe"/>
  47. </div>
  48. <script>
  49. var app = new Vue({
  50. el: '#app',
  51. data: {
  52. user: "",
  53. pwd: "",
  54. sex: "2",
  55. hobby: ["22"],
  56. city: "sz",
  57. company: ["22", "33"],
  58. more: '...'
  59. },
  60. methods: {
  61. clickMe: function () {
  62. console.log(this.user, this.pwd, this.sex, this.hobby, this.city, this.company, this.more);
  63. },
  64. }
  65. })
  66. </script>
  67. </body>
  68. </html>
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <div>
  11. 用户名:<input type="text" v-model="info.user">
  12. </div>
  13. <div>
  14. 密码:<input type="password" v-model="info.pwd">
  15. </div>
  16. <div>
  17. 性别:
  18. <input type="radio" v-model="info.sex" value="1">
  19. <input type="radio" v-model="info.sex" value="2">
  20. </div>
  21. <div>
  22. 爱好:
  23. <input type="checkbox" v-model="info.hobby" value="11">篮球
  24. <input type="checkbox" v-model="info.hobby" value="22">足球
  25. <input type="checkbox" v-model="info.hobby" value="33">评判求
  26. </div>
  27. <div>
  28. 城市:
  29. <select v-model="info.city">
  30. <option value="sh">上海</option>
  31. <option value="bj">北京</option>
  32. <option value="sz">深圳</option>
  33. </select>
  34. </div>
  35. <div>
  36. 擅长领域:
  37. <select v-model="info.company" multiple>
  38. <option value="11">技术</option>
  39. <option value="22">销售</option>
  40. <option value="33">运营</option>
  41. </select>
  42. </div>
  43. <div>
  44. 其他:<textarea v-model="info.more"></textarea>
  45. </div>
  46. <input type="button" value="注 册" v-on:click="clickMe"/>
  47. </div>
  48. <script>
  49. var app = new Vue({
  50. el: '#app',
  51. data: {
  52. info: {
  53. user: "",
  54. pwd: "",
  55. sex: "2",
  56. hobby: ["22"],
  57. city: "sz",
  58. company: ["22", "33"],
  59. more: '...'
  60. }
  61. },
  62. methods: {
  63. clickMe: function () {
  64. console.log(this.info);
  65. },
  66. }
  67. })
  68. </script>
  69. </body>
  70. </html>

v-for

用户数据进行循环并展示。

示例1:

  1. <div id="app">
  2. <ul>
  3. <!--会生成三个li标签-->
  4. <li v-for="item in dataList">{{ item }}</li>
  5. </ul>
  6. </div>
  7. <script>
  8. var app = new Vue({
  9. el: '#app',
  10. data: {
  11. dataList: ["郭德纲", "于谦", "三哥"],
  12. }
  13. })
  14. </script>

示例2:

  1. <div id="app">
  2. <ul>
  3. <!--可以得到值和索引 item是值 idx是索引-->
  4. <li v-for="(item,idx) in dataList">{{idx}} - {{ item }}</li>
  5. </ul>
  6. </div>
  7. <script>
  8. var app = new Vue({
  9. el: '#app',
  10. data: {
  11. dataList: ["郭德纲", "于谦", "三哥"],
  12. }
  13. })
  14. </script>

示例3:

  1. <div id="app">
  2. <ul>
  3. <!--循环字典时 value 是值 key 是键-->
  4. <li v-for="(value,key) in dataDict">{{key}} - {{ value }}</li>
  5. </ul>
  6. </div>
  7. <script>
  8. var app = new Vue({
  9. el: '#app',
  10. data: {
  11. dataDict: {
  12. id: 1,
  13. age: 18,
  14. name: "xxx"
  15. }
  16. }
  17. })
  18. </script>

示例4:

  1. <div id="app">
  2. <ul>
  3. <!--此时的item是一个字典,通过item.取值-->
  4. <li v-for="(item,idx) in cityList">{{item.id}} - {{ item.text }}</li>
  5. </ul>
  6. </div>
  7. <script>
  8. var app = new Vue({
  9. el: '#app',
  10. data: {
  11. cityList: [
  12. {id: 11, text: "上海"},
  13. {id: 12, text: "北京"},
  14. {id: 13, text: "深圳"},
  15. ]
  16. }
  17. })
  18. </script>

实例5:

  1. <ul>
  2. <li> <span>id 11</span> <span>text 上海</span> </li>
  3. 。。
  4. 。。
  5. </ul>
  1. <div id="app">
  2. <ul>
  3. <!--支持双层循环-->
  4. <li v-for="(item,idx) in cityList">
  5. <span v-for="(v,k) in item">{{k}} {{v}}</span>
  6. </li>
  7. </ul>
  8. </div>
  9. <script>
  10. var app = new Vue({
  11. el: '#app',
  12. data: {
  13. cityList: [
  14. {id: 11, text: "上海"},
  15. {id: 12, text: "北京"},
  16. {id: 13, text: "深圳"},
  17. ]
  18. }
  19. })
  20. </script>

v-on

事件相关的指令,例如:

  1. v-on:click 点击
  2. v-on:dblclick 双击
  3. v-on:mouseover,
  4. v-on:mouseout,
  5. v-on:change
  6. v-on:focus
  7. ...
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <ul>
  11. <li v-on:click="clickMe">点击</li>
  12. <!--简便写法-->
  13. <li @click="clickMe">点击</li>
  14. <li v-on:dblclick="doSomething('双击')">双击</li>
  15. <!--可以传参-->
  16. <li v-on:mouseover="doSomething('进入')" v-on:mouseout="doSomething('离开')">进入&离开</li>
  17. </ul>
  18. </div>
  19. <script>
  20. var app = new Vue({
  21. el: '#app',
  22. data: {},
  23. methods: {
  24. clickMe: function () {
  25. alert("点击了")
  26. },
  27. doSomething: function (msg) {
  28. console.log(msg);
  29. }
  30. }
  31. })
  32. </script>
  33. </body>
  34. </html>

案例

数据的管理包括对数据:展示、动态添加、删除、修改。

  • 数据列表展示
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. .penal {
  9. border: 1px solid #dddddd;
  10. margin: 20px 0 0 0;
  11. padding: 10px;
  12. border-bottom: 0;
  13. background-color: #d9d9d9;
  14. }
  15. .table {
  16. width: 100%;
  17. border-collapse: collapse;
  18. border-spacing: 0;
  19. }
  20. .table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
  21. padding: 8px;
  22. vertical-align: top;
  23. border: 1px solid #ddd;
  24. text-align: left;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <div id="app">
  30. <h3 class="penal">数据列表</h3>
  31. <table class="table">
  32. <thead>
  33. <tr>
  34. <td>姓名</td>
  35. <td>年龄</td>
  36. </tr>
  37. </thead>
  38. <tbody>
  39. <tr v-for="item in dataList">
  40. <td>{{item.name}}</td>
  41. <td>{{item.age}}</td>
  42. </tr>
  43. </tbody>
  44. </table>
  45. </div>
  46. <script>
  47. var app = new Vue({
  48. el: '#app',
  49. data: {
  50. dataList: [
  51. {"name": "武沛齐", "age": 19},
  52. {"name": "alex", "age": 89},
  53. ]
  54. }
  55. })
  56. </script>
  57. </body>
  58. </html>
  • 数据添加
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. .penal {
  9. border: 1px solid #dddddd;
  10. margin: 20px 0 0 0;
  11. padding: 10px;
  12. border-bottom: 0;
  13. background-color: #d9d9d9;
  14. }
  15. .table {
  16. width: 100%;
  17. border-collapse: collapse;
  18. border-spacing: 0;
  19. }
  20. .table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
  21. padding: 8px;
  22. vertical-align: top;
  23. border: 1px solid #ddd;
  24. text-align: left;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <div id="app">
  30. <h3 class="penal">表单区域</h3>
  31. <div>
  32. <div>
  33. <label>姓名</label>
  34. <input type="text" v-model="user">
  35. </div>
  36. <div>
  37. <label>年龄</label>
  38. <input type="text" v-model="age">
  39. <input type="button" value="新建" @click="addUser">
  40. </div>
  41. </div>
  42. <h3 class="penal">数据列表</h3>
  43. <table class="table">
  44. <thead>
  45. <tr>
  46. <td>姓名</td>
  47. <td>年龄</td>
  48. </tr>
  49. </thead>
  50. <tbody>
  51. <tr v-for="item in dataList">
  52. <td>{{item.name}}</td>
  53. <td>{{item.age}}</td>
  54. </tr>
  55. </tbody>
  56. </table>
  57. </div>
  58. <script>
  59. var app = new Vue({
  60. el: '#app',
  61. data: {
  62. user: "",
  63. age: "",
  64. dataList: [
  65. {name: "武沛齐", age: 19},
  66. {name: "alex", age: 89},
  67. ]
  68. },
  69. methods: {
  70. addUser: function () {
  71. let row = {name: this.user, age: this.age};
  72. this.dataList.push(row);
  73. this.user = "";
  74. this.age = "";
  75. }
  76. }
  77. })
  78. </script>
  79. </body>
  80. </html>
  • 删除数据
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. .penal {
  9. border: 1px solid #dddddd;
  10. margin: 20px 0 0 0;
  11. padding: 10px;
  12. border-bottom: 0;
  13. background-color: #d9d9d9;
  14. }
  15. .table {
  16. width: 100%;
  17. border-collapse: collapse;
  18. border-spacing: 0;
  19. }
  20. .table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
  21. padding: 8px;
  22. vertical-align: top;
  23. border: 1px solid #ddd;
  24. text-align: left;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <div id="app">
  30. <h3 class="penal">表单区域</h3>
  31. <div>
  32. <div>
  33. <label>姓名</label>
  34. <input type="text" v-model="user">
  35. </div>
  36. <div>
  37. <label>年龄</label>
  38. <input type="text" v-model="age">
  39. <input type="button" value="新建" @click="addUser">
  40. </div>
  41. </div>
  42. <h3 class="penal">数据列表</h3>
  43. <table class="table">
  44. <thead>
  45. <tr>
  46. <td>姓名</td>
  47. <td>年龄</td>
  48. <td>操作</td>
  49. </tr>
  50. </thead>
  51. <tbody>
  52. <tr v-for="(item,idx) in dataList">
  53. <td>{{item.name}}</td>
  54. <td>{{item.age}}</td>
  55. <td>
  56. // :data-idx="idx" 会将idx的值传递给deleteRow函数
  57. <input type="button" value="删除" @click="deleteRow" :data-idx="idx"/>
  58. </td>
  59. </tr>
  60. </tbody>
  61. </table>
  62. </div>
  63. <script>
  64. var app = new Vue({
  65. el: '#app',
  66. data: {
  67. user: "",
  68. age: "",
  69. dataList: [
  70. {name: "武沛齐", age: 19},
  71. {name: "alex", age: 89},
  72. ]
  73. },
  74. methods: {
  75. addUser: function () {
  76. let row = {name: this.user, age: this.age};
  77. this.dataList.push(row);
  78. this.user = "";
  79. this.age = "";
  80. },
  81. deleteRow: function (event) {
  82. // event当前事件的触发对象是默认传递进来的
  83. // event.target.dataset默认格式
  84. // 根据索引删除dataList中的值
  85. let idx = event.target.dataset.idx;
  86. // 1是删除1个
  87. this.dataList.splice(idx, 1);
  88. }
  89. }
  90. })
  91. </script>
  92. </body>
  93. </html>
  • 编辑修改数据
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. .penal {
  9. border: 1px solid #dddddd;
  10. margin: 20px 0 0 0;
  11. padding: 10px;
  12. border-bottom: 0;
  13. background-color: #d9d9d9;
  14. }
  15. .table {
  16. width: 100%;
  17. border-collapse: collapse;
  18. border-spacing: 0;
  19. }
  20. .table > tbody > tr > td, .table > tbody > tr > th, .table > tfoot > tr > td, .table > tfoot > tr > th, .table > thead > tr > td, .table > thead > tr > th {
  21. padding: 8px;
  22. vertical-align: top;
  23. border: 1px solid #ddd;
  24. text-align: left;
  25. }
  26. </style>
  27. </head>
  28. <body>
  29. <div id="app">
  30. <h3 class="penal">表单区域</h3>
  31. <div>
  32. <div>
  33. <label>姓名</label>
  34. <input type="text" v-model="user">
  35. </div>
  36. <div>
  37. <label>年龄</label>
  38. <input type="text" v-model="age">
  39. <input type="button" :value="title" @click="addUser">
  40. </div>
  41. </div>
  42. <h3 class="penal">数据列表</h3>
  43. <table class="table">
  44. <thead>
  45. <tr>
  46. <td>姓名</td>
  47. <td>年龄</td>
  48. <td>操作</td>
  49. </tr>
  50. </thead>
  51. <tbody>
  52. <tr v-for="(item,idx) in dataList">
  53. <td>{{item.name}}</td>
  54. <td>{{item.age}}</td>
  55. <td>
  56. <input type="button" value="删除" @click="deleteRow" :data-idx="idx"/>
  57. <input type="button" value="编辑" @click="editRow" :data-idx="idx"/>
  58. </td>
  59. </tr>
  60. </tbody>
  61. </table>
  62. </div>
  63. <script>
  64. var app = new Vue({
  65. el: '#app',
  66. data: {
  67. editIndex: undefined,
  68. title: "新建",
  69. user: "",
  70. age: "",
  71. dataList: [
  72. {name: "武沛齐", age: 19},
  73. {name: "alex", age: 89},
  74. ]
  75. },
  76. methods: {
  77. addUser: function () {
  78. if (this.editIndex) {
  79. // 修改
  80. this.dataList[this.editIndex].name = this.user;
  81. this.dataList[this.editIndex].age = this.age;
  82. } else {
  83. let row = {name: this.user, age: this.age};
  84. this.dataList.push(row);
  85. }
  86. this.user = "";
  87. this.age = "";
  88. this.editIndex = undefined;
  89. this.title = "新建";
  90. },
  91. deleteRow: function (event) {
  92. // 根据索引删除dataList中的值
  93. let idx = event.target.dataset.idx;
  94. this.dataList.splice(idx, 1);
  95. },
  96. editRow: function (event) {
  97. let idx = event.target.dataset.idx;
  98. // let name = this.dataList[idx].name;
  99. // let age = this.dataList[idx].age;
  100. // let {id, name} = {id: 1, name: "武沛齐"};
  101. // console.log(id, name);
  102. let {name, age} = this.dataList[idx];
  103. this.user = name;
  104. this.age = age;
  105. this.title = "编辑";
  106. this.editIndex = idx;
  107. }
  108. }
  109. })
  110. </script>
  111. </body>
  112. </html>

v-if指令

条件指令 用来做判断 条件不成立标签都不会渲染到页面

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. //判断 isLogin 的值是否为True 是的话执行{{user}}
  11. <a v-if="isLogin">{{user}}</a>
  12. //v-else 就是else
  13. <a v-else>登录</a>
  14. </div>
  15. <script>
  16. var app = new Vue({
  17. el: '#app',
  18. data: {
  19. isLogin: false,
  20. user: "武沛齐"
  21. }
  22. })
  23. </script>
  24. </body>
  25. </html>
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <h1 v-if="v1">阿里无人区</h1>
  11. <h1 v-if="v2">去西藏</h1>
  12. <h1 v-else>去新疆</h1>
  13. <div v-if="v3 === '北京'">
  14. <h1>天安门</h1>
  15. </div>
  16. <div v-else-if="v3 === '新疆'">
  17. <h1>乌鲁木齐</h1>
  18. </div>
  19. <div v-else-if="v3 ==='西藏'">
  20. <h1>拉萨</h1>
  21. </div>
  22. <div v-else>
  23. <h1>大理</h1>
  24. </div>
  25. </div>
  26. <script>
  27. var app = new Vue({
  28. el: '#app',
  29. data: {
  30. v1: true,
  31. v2: true,
  32. v3: "新疆"
  33. }
  34. })
  35. </script>
  36. </body>
  37. </html>

v-show

根据条件显示或隐藏(标签都会渲染到页面)。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <h1 v-show="v1">可可西里</h1>
  11. <h1 v-show="!v1">罗布泊</h1>
  12. </div>
  13. <script>
  14. var app = new Vue({
  15. el: '#app',
  16. data: {
  17. v1: false,
  18. }
  19. })
  20. </script>
  21. </body>
  22. </html>
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <style>
  8. label {
  9. width: 60px;
  10. display: inline-block;
  11. text-align: right;
  12. margin-right: 8px;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <div id="app">
  18. // isSms=false 将isSms对应的值修改为false
  19. <input type="button" value="密码登录" @click="isSms=false"/>
  20. <input type="button" value="短信登录" @click="isSms=true"/>
  21. <div v-show="isSms">
  22. <p>
  23. <label>手机号</label>
  24. <input type="text" placeholder="手机号">
  25. </p>
  26. <p>
  27. <label>验证码</label>
  28. <input type="text" placeholder="验证码">
  29. </p>
  30. </div>
  31. <div v-show="!isSms">
  32. <p>
  33. <label>用户名</label>
  34. <input type="text" placeholder="用户名">
  35. </p>
  36. <p>
  37. <label>密码</label>
  38. <input type="password" placeholder="密码">
  39. </p>
  40. </div>
  41. </div>
  42. <script>
  43. var app = new Vue({
  44. el: '#app',
  45. data: {
  46. isSms: false,
  47. }
  48. })
  49. </script>
  50. </body>
  51. </html>

登录案例

在编写案例之前,现在来学下axios,他是一个HTTP 库,可以发送Http请求。

  1. // 引入 axios库
  2. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  3. // axios 里面放一个对象 params是url中携带的参数,data是请求体中携带的参数
  4. <script>
  5. axios({
  6. method: "post",
  7. url: 'https://api.luf...ord/login/',
  8. params: {
  9. v1:123,
  10. v2:456
  11. },
  12. data: {
  13. name:"武沛齐",
  14. pwd:"123"
  15. },
  16. headers: {
  17. "Content-Type": "application/json"
  18. }
  19. }).then(function (res) {
  20. console.log(res.data);
  21. }).catch(function (error) {
  22. console.log(error);
  23. })
  24. </script>
  25. .then是发送请求后执行的回调函数res是请求返回的内容,catch回调函数是捕获错误信息的
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  8. <style>
  9. label {
  10. width: 60px;
  11. display: inline-block;
  12. text-align: right;
  13. margin-right: 8px;
  14. }
  15. </style>
  16. </head>
  17. <body>
  18. <div id="app">
  19. <input type="button" value="密码登录" @click="isSms=false"/>
  20. <input type="button" value="短信登录" @click="isSms=true"/>
  21. <div v-show="isSms">
  22. <p>
  23. <label>手机号</label>
  24. <input type="text" placeholder="手机号" v-model="sms.mobile">
  25. </p>
  26. <p>
  27. <label>验证码</label>
  28. <input type="text" placeholder="验证码" v-model="sms.code">
  29. </p>
  30. </div>
  31. <div v-show="!isSms">
  32. <p>
  33. <label>用户名</label>
  34. <input type="text" placeholder="用户名" v-model="info.username">
  35. </p>
  36. <p>
  37. <label>密码</label>
  38. <input type="password" placeholder="密码" v-model="info.password">
  39. </p>
  40. </div>
  41. <input type="button" value="登 录" @click="loginForm"/>
  42. </div>
  43. <script>
  44. var app = new Vue({
  45. el: '#app',
  46. data: {
  47. isSms: false,
  48. info: {
  49. username: "",
  50. password: "",
  51. },
  52. sms: {
  53. mobile: "",
  54. code: ""
  55. }
  56. },
  57. methods: {
  58. loginForm: function () {
  59. // 1.获取用户输入的值
  60. let dataDict = this.isSms ? this.sms : this.info;
  61. let url;
  62. if (this.isSms) {
  63. url = "https://api.luffycity.com/api/v1/auth/mobile/login/?loginWay=mobile";
  64. } else {
  65. url = "https://api.luffycity.com/api/v1/auth/password/login/?loginWay=password";
  66. }
  67. // 2.想某个地址发送网络请求 axios
  68. // https://api.luffycity.com/api/v1/auth/password/login/?loginWay=password
  69. // {"username":"alex123","password":"999"}
  70. // https://api.luffycity.com/api/v1/auth/mobile/login/?loginWay=mobile
  71. // {"mobile":"18630087660","code":"123123"}
  72. axios({
  73. method: "post",
  74. url: url,
  75. data: dataDict,
  76. headers: {
  77. "Content-Type": "application/json"
  78. }
  79. }).then(function (res) {
  80. if (res.data.code === -1) {
  81. alert(res.data.msg);
  82. return;
  83. }
  84. // 登录成功后跳转
  85. window.location.href = "https://www.luffycity.com"
  86. }).catch(function (error) {
  87. alert("请求异常,请重新操作。")
  88. })
  89. }
  90. }
  91. })
  92. </script>
  93. </body>
  94. </html>

组件化开发

在开发过程中,我们可以将页面中 某一部分 的功能编写成一个组件,然后再在页面上进行引用。

  • 有利于划分功能模块的开发(HTML、CSS、JavaScript等相关代码都集成到组件中)。
  • 有利于重用

局部组件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <h1>=======当前页面=======</h1>
  11. {{name}}
  12. <h1>=======引入子组件=======</h1>
  13. <Demo></Demo> //使用组件
  14. <Demo></Demo> //组件可以复用
  15. <Bb></Bb>
  16. <Bb></Bb>
  17. <hr/>
  18. <Bb></Bb>
  19. </div>
  20. <script>
  21. //创建子组件 template子组件模板 就是 html页面 {{msg}}是 data定义的函数的返回值一定是返回值才能在 模板中引用
  22. const Demo = {
  23. data:function() {
  24. return {
  25. msg: '哈哈哈哈哈'
  26. }
  27. },
  28. template: `
  29. <div>
  30. <h1>{{msg}}</h1>
  31. <input type="text" v-model="msg"/>
  32. <input type="button" @click="showMeg" value="点我呀">
  33. </div>
  34. `,
  35. methods: {
  36. showMeg: function () {
  37. alert(this.msg);
  38. }
  39. }
  40. }
  41. //创建子组件
  42. const Bili = {
  43. // 组件中的data是一个方法,并返回值(与Vue对象创建不同)
  44. data:function() {
  45. return {
  46. dataList: [
  47. {"id": 1, "title": "路飞学城倒闭了"},
  48. {"id": 2, "title": "老板和保洁阿姨跑了"},
  49. ]
  50. }
  51. },
  52. template: `
  53. <div>
  54. <h1>数据列表</h1>
  55. <table border="1">
  56. <thead>
  57. <tr>
  58. <th>ID</th>
  59. <th>标题</th>
  60. </tr>
  61. </thead>
  62. <tbody>
  63. <tr v-for="item in dataList">
  64. <td>{{item.id}}</td>
  65. <td>{{item.title}}</td>
  66. </tr>
  67. </tbody>
  68. </table>
  69. </div>
  70. `
  71. }
  72. var app = new Vue({
  73. el: '#app',
  74. data: {
  75. name: "武沛齐",
  76. },
  77. <!--components放的是待指组件的名字,想当于挂载组件-->
  78. components: {
  79. Demo,
  80. Bb: Bili
  81. },
  82. methods: {}
  83. })
  84. </script>
  85. </body>
  86. </html>

全局组件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <h1>=======当前页面=======</h1>
  11. {{name}}
  12. <h1>=======引入子组件=======</h1>
  13. <Demo></Demo>
  14. <Demo></Demo>
  15. <Bili></Bili>
  16. <Bili></Bili>
  17. </div>
  18. <script>
  19. //创建子组件 Demo 组件的名字
  20. Vue.component('Demo', {
  21. data: function () {
  22. return {
  23. msg: '哈哈哈哈哈'
  24. }
  25. },
  26. template: `
  27. <div>
  28. <h1>{{msg}}</h1>
  29. <input type="text" v-model="msg"/>
  30. <input type="button" @click="showMeg" value="点我呀">
  31. </div>
  32. `,
  33. methods: {
  34. showMeg: function () {
  35. alert(this.msg);
  36. }
  37. }
  38. });
  39. //创建子组件
  40. Vue.component('Bili', {
  41. // 组件中的data是一个方法,并返回值(与Vue对象创建不同)
  42. data: function () {
  43. return {
  44. dataList: [
  45. {"id": 1, "title": "路飞学城倒闭了"},
  46. {"id": 2, "title": "老板和保洁阿姨跑了"},
  47. ]
  48. }
  49. },
  50. template: `
  51. <div>
  52. <h1>数据列表</h1>
  53. <table border="1">
  54. <thead>
  55. <tr>
  56. <th>ID</th>
  57. <th>标题</th>
  58. </tr>
  59. </thead>
  60. <tbody>
  61. <tr v-for="item in dataList">
  62. <td>{{item.id}}</td>
  63. <td>{{item.title}}</td>
  64. </tr>
  65. </tbody>
  66. </table>
  67. </div>
  68. `
  69. });
  70. var app = new Vue({
  71. el: '#app',
  72. data: {
  73. name: "武沛齐",
  74. },
  75. methods: {}
  76. })
  77. </script>
  78. </body>
  79. </html>

vue-router 组件

vue + vue-router组件可以实现 SPA(single Page Application),即:单页面应用。

单页面应用,简而言之就是项目只有一个页面。

一个页面如何呈现多种界面的效果呢?

  • 基于vue开发多个组件,例如:活动组件、课程组件、咨询组件
  • 在页面上 vue-router 用来管理这些组件,用户点击某个按钮,就显示特定的组件(数据基于Ajax获取)。

13.vue - 图1

官方地址:https://router.vuejs.org/zh/

下载地址:https://unpkg.com/vue-router@4

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <!-- vue-router.js 依赖 vue.js -->
  7. <script src="vue.js"></script>
  8. <script src="vue-router.js"></script>
  9. </head>
  10. <body>
  11. </body>
  12. </html>

注意:后期用脚手架开发时,可以直接使用npm下载和引用。

快速上手

13.vue - 图2

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .container {
  11. width: 980px;
  12. margin: 0 auto;
  13. }
  14. .menu {
  15. height: 48px;
  16. background-color: #499ef3;
  17. line-height: 48px;
  18. }
  19. .menu a {
  20. color: white;
  21. text-decoration: none;
  22. padding: 0 10px;
  23. }
  24. </style>
  25. <script src="vue.js"></script>
  26. <script src="vue-router.js"></script>
  27. </head>
  28. <body>
  29. <div id="app">
  30. <div class="menu">
  31. <div class="container">
  32. //router-link 相当于a标签 定义菜单一般使用router-link
  33. <router-link to="/">Logo</router-link>
  34. <router-link to="/home">首页</router-link>
  35. <router-link to="/course">课程</router-link>
  36. <router-link to="/news">资讯</router-link>
  37. </div>
  38. </div>
  39. <div class="container">
  40. //router-view 里面放的是加载的组件
  41. <router-view></router-view>
  42. </div>
  43. </div>
  44. <script>
  45. //定义了三个组件
  46. const Home = {template: '<div>首页内容...</div>'}
  47. const Course = {template: '<div>课程内容..</div>'}
  48. const News = {template: '<div>资讯内容..</div>'}
  49. //定义VueRouter 管理三个组件 访问'/'路径 加载Home组件
  50. const router = new VueRouter({
  51. routes: [
  52. {
  53. path: '/',
  54. component: Home
  55. },
  56. {path: '/home', component: Home},
  57. {path: '/course', component: Course},
  58. {path: '/news', component: News}
  59. ],
  60. })
  61. var app = new Vue({
  62. el: '#app',
  63. data: {
  64. name: "武沛齐",
  65. },
  66. methods: {},
  67. router: router //router 添加到router
  68. })
  69. </script>
  70. </body>
  71. </html>

案例 第一版

13.vue - 图3

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .container {
  11. width: 1100px;
  12. margin: 0 auto;
  13. }
  14. .menu {
  15. height: 48px;
  16. background-color: #499ef3;
  17. line-height: 48px;
  18. }
  19. .menu a {
  20. color: white;
  21. text-decoration: none;
  22. padding: 0 10px;
  23. }
  24. .course-list {
  25. display: flex;
  26. flex-wrap: wrap;
  27. justify-content: flex-start;
  28. }
  29. .course-list .item {
  30. width: 248px;
  31. padding: 10px;
  32. border: 1px solid #dddddd;
  33. margin-right: 5px;
  34. margin-top: 10px;
  35. }
  36. .course-list .item img {
  37. width: 100%;
  38. height: 120px;
  39. }
  40. </style>
  41. // 引入环境
  42. <script src="vue.js"></script>
  43. <script src="vue-router.js"></script>
  44. <script src="axios.min.js"></script>
  45. </head>
  46. <body>
  47. <div id="app">
  48. <div class="menu">
  49. <div class="container">
  50. <router-link to="/">路飞学城</router-link>
  51. <router-link to="/home">首页</router-link>
  52. <router-link to="/course">课程</router-link>
  53. <router-link to="/news">资讯</router-link>
  54. </div>
  55. </div>
  56. <div class="container">
  57. <router-view></router-view>
  58. </div>
  59. </div>
  60. <script>
  61. const Home = {
  62. data: function () {
  63. return {
  64. title: "欢迎使用路飞学城"
  65. }
  66. },
  67. template: `<h2>{{title}}</h2>`
  68. }
  69. const Course = {
  70. data: function () {
  71. return {
  72. courseList: []
  73. }
  74. },
  75. created: function () {
  76. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面相关的DOM创建并显示在页面上】
  77. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  78. - 不可以去操作DOM,例如:document.getElementById (未创建)
  79. */
  80. axios({
  81. method: "get",
  82. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=0',
  83. headers: {
  84. "Content-Type": "application/json"
  85. }
  86. }).then((res) => {
  87. this.courseList = res.data.data.result;
  88. })
  89. },
  90. mounted: function () {
  91. /* DOM对象已在页面上生成,此时就可以 */
  92. },
  93. template: `
  94. <div class="course-list">
  95. <div class="item" v-for="item in courseList">
  96. <img :src="item.cover" alt="">
  97. <a>{{item.name}}</a>
  98. </div>
  99. </div>`
  100. }
  101. const News = {
  102. data: function () {
  103. return {
  104. dataList: []
  105. }
  106. },
  107. created: function () {
  108. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  109. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  110. - 不可以去操作DOM,例如:document.getElementById (未创建)
  111. */
  112. axios({
  113. method: "get",
  114. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=10',
  115. headers: {
  116. "Content-Type": "application/json"
  117. }
  118. }).then((res) => {
  119. this.dataList = res.data.data.result;
  120. })
  121. },
  122. template: `<ul><li v-for="item in dataList">{{item.name}}</li></ul>`
  123. }
  124. const router = new VueRouter({
  125. routes: [
  126. {path: '/', component: Home},
  127. {path: '/home', component: Home},
  128. {path: '/course', component: Course},
  129. {path: '/news', component: News}
  130. ],
  131. //mode: 'history'
  132. })
  133. var app = new Vue({
  134. el: '#app',
  135. data: {},
  136. methods: {},
  137. router: router
  138. })
  139. </script>
  140. </body>
  141. </html>

路由和传值

当某个组件可以根据某些参数值的不同,展示不同效果时,需要用到动态路由。

例如:访问网站看到课程列表,点击某个课程,就可以跳转到课程详细页面(根据课程ID不同展示不同数据)。

如何来设置动态路由呢?

  • 定义路由
  1. const router = new VueRouter({
  2. routes: [
  3. { path: '/', component: Home}, //component是组件的名字
  4. { path: '/course', component: Course, name: "Course"} // name待指这个路由
  5. { path: '/detail/:id', component: Detail, name: "Detail"} //:id 表示/detail/可以跟参数
  6. ],
  7. })
  • HTML展示
  1. <div>
  2. <router-link to="/">首页</router-link>
  3. <router-link to="/course">课程</router-link>
  4. <router-link to="/detail/123">课程</router-link>
  5. <router-link :to="{path:'/course'}">课程</router-link>
  6. <router-link :to="{path:'/course?size=19&page=2'}">课程</router-link>
  7. <router-link :to="{path:'/course', query:{size:19,page:2}">课程</router-link>
  8. <router-link :to="{name:'Course'}">课程</router-link>
  9. <router-link :to="{name:'Course', query:{size:19,page:2} }">课程</router-link>
  10. //query就是在url中传参,?size-123&
  11. <router-link :to="{path:'/detail/22',query:{size:123}}">Linux</router-link>
  12. //params:{id:3}是指给/detail/:id中的:id传参数
  13. <router-link :to="{name:'Detail',params:{id:3}, query:{size:29}}">网络安全</router-link>
  14. </div>
  15. <h1>内容区域</h1>
  16. <router-view></router-view>
  • 组件获取URL传值和GET参数
  1. const Detail = {
  2. data: function () {
  3. return {
  4. title: "详细页面",
  5. paramDict: null,
  6. queryDict: null,
  7. }
  8. },
  9. created: function () {
  10. this.paramDict = this.$route.params; //this.$route.params读的是'/detail/:id'这种格式传的值
  11. this.queryDict = this.$route.query;//this.$route.query读的是url中传过来的值?后的值
  12. // 发送axios请求
  13. },
  14. template: `<div><h2>{{title}}</h2><div>当前请求的数据 {{paramDict}} {{queryDict}}</div></div>`
  15. }

案例:路飞学城(第2版)

点击课程,查看课程详细页面。

13.vue - 图4

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .container {
  11. width: 1100px;
  12. margin: 0 auto;
  13. }
  14. .menu {
  15. height: 48px;
  16. background-color: #499ef3;
  17. line-height: 48px;
  18. }
  19. .menu a {
  20. color: white;
  21. text-decoration: none;
  22. padding: 0 10px;
  23. }
  24. .course-list {
  25. display: flex;
  26. flex-wrap: wrap;
  27. justify-content: flex-start;
  28. }
  29. .course-list .item {
  30. width: 248px;
  31. padding: 10px;
  32. border: 1px solid #dddddd;
  33. margin-right: 5px;
  34. margin-top: 10px;
  35. }
  36. .course-list .item img {
  37. width: 100%;
  38. height: 120px;
  39. }
  40. </style>
  41. <script src="vue.js"></script>
  42. <script src="vue-router.js"></script>
  43. <script src="axios.min.js"></script>
  44. </head>
  45. <body>
  46. <div id="app">
  47. <div class="menu">
  48. <div class="container">
  49. <router-link to="/">路飞学城</router-link>
  50. <router-link to="/home">首页</router-link>
  51. <router-link to="/course">课程</router-link>
  52. <router-link to="/news">资讯</router-link>
  53. </div>
  54. </div>
  55. <div class="container">
  56. <router-view></router-view>
  57. </div>
  58. </div>
  59. <script>
  60. const Home = {
  61. data: function () {
  62. return {
  63. title: "欢迎使用路飞学城"
  64. }
  65. },
  66. template: `<h2>{{title}}</h2>`
  67. }
  68. const Course = {
  69. data: function () {
  70. return {
  71. courseList: []
  72. }
  73. },
  74. created: function () {
  75. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  76. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  77. - 不可以去操作DOM,例如:document.getElementById (未创建)
  78. */
  79. axios({
  80. method: "get",
  81. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=0',
  82. headers: {
  83. "Content-Type": "application/json"
  84. }
  85. }).then((res) => {
  86. this.courseList = res.data.data.result;
  87. })
  88. },
  89. mounted: function () {
  90. /* DOM对象已在页面上生成,此时就可以 */
  91. },
  92. template: `
  93. <div class="course-list">
  94. <div class="item" v-for="item in courseList">
  95. <router-link :to="{name:'Detail',params:{id:item.id}}">
  96. <img :src="item.cover" alt="">
  97. <a>{{item.name}}</a>
  98. </router-link>
  99. </div>
  100. </div>`
  101. }
  102. const News = {
  103. data: function () {
  104. return {
  105. dataList: []
  106. }
  107. },
  108. created: function () {
  109. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  110. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  111. - 不可以去操作DOM,例如:document.getElementById (未创建)
  112. */
  113. axios({
  114. method: "get",
  115. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=10',
  116. headers: {
  117. "Content-Type": "application/json"
  118. }
  119. }).then((res) => {
  120. this.dataList = res.data.data.result;
  121. })
  122. },
  123. template: `<ul><li v-for="item in dataList">{{item.name}}</li></ul>`
  124. }
  125. const Detail = {
  126. data: function () {
  127. return {
  128. title: "详细页面",
  129. courseId: null
  130. }
  131. },
  132. created: function () {
  133. this.courseId = this.$route.params.id;
  134. // 此处可以根据课程ID,发送ajax请求获取课程详细信息
  135. },
  136. template: `<div><h2>课程详细页面</h2><div>当前课程ID为:{{courseId}}</div></div>`
  137. }
  138. const router = new VueRouter({
  139. routes: [
  140. {path: '/', component: Home},
  141. {path: '/home', component: Home},
  142. {path: '/course', component: Course},
  143. {path: '/news', component: News},
  144. {path: '/detail/:id', component: Detail, name: 'Detail'}
  145. ],
  146. //mode: 'history'
  147. })
  148. var app = new Vue({
  149. el: '#app',
  150. data: {},
  151. methods: {},
  152. router: router
  153. })
  154. </script>
  155. </body>
  156. </html>

页面无法刷新问题

上述编写案例是没有问题,但如果在开发中会涉及到 同一个路由的跳转(默认不会重新加载页面,数据无法获取)。

例如:在详细页面再出现一个课程推荐,即:在课程详细,点击推荐的课程后跳转到课程详细页面(课程ID不同),此时课程的ID还是原来加载的ID,无法获取推荐课程的ID。

如何解决呢?

在课程详细的组件中设置watch属性即可,watch会监测$route 值,一旦发生变化,就执行相应的函数。

  1. const Detail = {
  2. data: function () {
  3. return {
  4. title: "详细页面",
  5. courseId: null,
  6. }
  7. },
  8. created: function () {
  9. this.courseId = this.$route.params.id;
  10. this.getCourseDetail();
  11. },
  12. watch: {
  13. //监听路由里面的值发生改变就执行定义的这个函数 to表示要跳转到的那个路由相关的值,from表示原来页面的值
  14. $route:function(to, from) {
  15. this.courseId = to.params.id;
  16. // this.getCourseDetail();
  17. }
  18. },
  19. methods: {
  20. getCourseDetail: function () {
  21. // 根据this.courseId获取课程详细信息
  22. }
  23. },
  24. template: `<div><h2>{{title}}</h2><div>当前请求的数据 {{paramDict}} {{queryDict}}</div></div>`
  25. }

案例:路飞学城(第3版)

在详细页面实现推荐课程

13.vue - 图5

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .container {
  11. width: 1100px;
  12. margin: 0 auto;
  13. }
  14. .menu {
  15. height: 48px;
  16. background-color: #499ef3;
  17. line-height: 48px;
  18. }
  19. .menu a {
  20. color: white;
  21. text-decoration: none;
  22. padding: 0 10px;
  23. }
  24. .course-list {
  25. display: flex;
  26. flex-wrap: wrap;
  27. justify-content: flex-start;
  28. }
  29. .course-list .item {
  30. width: 248px;
  31. padding: 10px;
  32. border: 1px solid #dddddd;
  33. margin-right: 5px;
  34. margin-top: 10px;
  35. }
  36. .course-list .item img {
  37. width: 100%;
  38. height: 120px;
  39. }
  40. </style>
  41. <script src="vue.js"></script>
  42. <script src="vue-router.js"></script>
  43. <script src="axios.min.js"></script>
  44. </head>
  45. <body>
  46. <div id="app">
  47. <div class="menu">
  48. <div class="container">
  49. <router-link to="/">路飞学城</router-link>
  50. <router-link to="/home">首页</router-link>
  51. <router-link to="/course">课程</router-link>
  52. <router-link to="/news">资讯</router-link>
  53. </div>
  54. </div>
  55. <div class="container">
  56. <router-view></router-view>
  57. </div>
  58. </div>
  59. <script>
  60. const Home = {
  61. data: function () {
  62. return {
  63. title: "欢迎使用路飞学城"
  64. }
  65. },
  66. template: `<h2>{{title}}</h2>`
  67. }
  68. const Course = {
  69. data: function () {
  70. return {
  71. courseList: []
  72. }
  73. },
  74. created: function () {
  75. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  76. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  77. - 不可以去操作DOM,例如:document.getElementById (未创建)
  78. */
  79. axios({
  80. method: "get",
  81. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=0',
  82. headers: {
  83. "Content-Type": "application/json"
  84. }
  85. }).then((res) => {
  86. this.courseList = res.data.data.result;
  87. })
  88. },
  89. mounted: function () {
  90. /* DOM对象已在页面上生成,此时就可以 */
  91. },
  92. template: `
  93. <div class="course-list">
  94. <div class="item" v-for="item in courseList">
  95. <router-link :to="{name:'Detail',params:{id:item.id}}">
  96. <img :src="item.cover" alt="">
  97. <a>{{item.name}}</a>
  98. </router-link>
  99. </div>
  100. </div>`
  101. }
  102. const News = {
  103. data: function () {
  104. return {
  105. dataList: []
  106. }
  107. },
  108. created: function () {
  109. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  110. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  111. - 不可以去操作DOM,例如:document.getElementById (未创建)
  112. */
  113. axios({
  114. method: "get",
  115. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=10',
  116. headers: {
  117. "Content-Type": "application/json"
  118. }
  119. }).then((res) => {
  120. this.dataList = res.data.data.result;
  121. })
  122. },
  123. template: `<ul><li v-for="item in dataList">{{item.name}}</li></ul>`
  124. }
  125. const Detail = {
  126. data: function () {
  127. return {
  128. title: "详细页面",
  129. courseId: null,
  130. hotCourseList: [
  131. {id: 1000, title: "python全栈开发"},
  132. {id: 2000, title: "异步编程"},
  133. ],
  134. }
  135. },
  136. created: function () {
  137. this.courseId = this.$route.params.id;
  138. // 此处可以根据课程ID,发送ajax请求获取课程详细信息
  139. this.getCourseDetail();
  140. },
  141. watch: {
  142. $route: function (to, from) {
  143. this.courseId = to.params.id;
  144. this.getCourseDetail();
  145. }
  146. },
  147. methods: {
  148. getCourseDetail: function () {
  149. // 根据this.courseId获取课程详细信息
  150. }
  151. },
  152. template: `
  153. <div>
  154. <h2>课程详细页面</h2>
  155. <div>当前课程ID为:{{courseId}}</div>
  156. <h3>课程推荐</h3>
  157. <ul>
  158. <li v-for="item in hotCourseList">
  159. <router-link :to="{name:'Detail', params:{id:item.id}}">{{item.title}}</router-link>
  160. </li>
  161. </ul>
  162. </div>`
  163. }
  164. const router = new VueRouter({
  165. routes: [
  166. {path: '/', component: Home},
  167. {path: '/home', component: Home},
  168. {path: '/course', component: Course},
  169. {path: '/news', component: News},
  170. {path: '/detail:id', component: Detail, name: 'Detail'}
  171. ],
  172. //mode: 'history'
  173. })
  174. var app = new Vue({
  175. el: '#app',
  176. data: {},
  177. methods: {},
  178. router: router
  179. })
  180. </script>
  181. </body>
  182. </html>

路由嵌套

13.vue - 图6

  1. const router = new VueRouter({
  2. routes: [
  3. {
  4. path: '/pins/',
  5. component: Pins,
  6. // children是子路由
  7. children: [
  8. {
  9. // 当 /pins/hot 匹配成功,
  10. // Hot组件 会被渲染在 Pins 的 <router-view> 中
  11. path: 'hot',
  12. component: Hot
  13. },
  14. {
  15. // 当 /pins/following 匹配成功,
  16. // Following组件 会被渲染在 Pins 的 <router-view> 中
  17. path: 'following',
  18. component: Following
  19. }
  20. ]
  21. }
  22. ]
  23. })

案例:路飞学城(第4版)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .container {
  11. width: 1100px;
  12. margin: 0 auto;
  13. }
  14. .menu {
  15. height: 48px;
  16. background-color: #499ef3;
  17. line-height: 48px;
  18. }
  19. .menu a {
  20. color: white;
  21. text-decoration: none;
  22. padding: 0 10px;
  23. }
  24. .course-list {
  25. display: flex;
  26. flex-wrap: wrap;
  27. justify-content: flex-start;
  28. }
  29. .course-list .item {
  30. width: 248px;
  31. padding: 10px;
  32. border: 1px solid #dddddd;
  33. margin-right: 5px;
  34. margin-top: 10px;
  35. }
  36. .course-list .item img {
  37. width: 100%;
  38. height: 120px;
  39. }
  40. </style>
  41. <script src="vue.js"></script>
  42. <script src="vue-router.js"></script>
  43. <script src="axios.min.js"></script>
  44. </head>
  45. <body>
  46. <div id="app">
  47. <div class="menu">
  48. <div class="container">
  49. <router-link to="/">路飞学城</router-link>
  50. <router-link to="/pins">沸点</router-link>
  51. <router-link to="/home">首页</router-link>
  52. <router-link to="/course">课程</router-link>
  53. <router-link to="/news">资讯</router-link>
  54. </div>
  55. </div>
  56. <div class="container">
  57. <router-view></router-view>
  58. </div>
  59. </div>
  60. <script>
  61. const Home = {
  62. data: function () {
  63. return {
  64. title: "欢迎使用路飞学城"
  65. }
  66. },
  67. template: `<h2>{{title}}</h2>`
  68. }
  69. const Course = {
  70. data: function () {
  71. return {
  72. courseList: []
  73. }
  74. },
  75. created: function () {
  76. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  77. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  78. - 不可以去操作DOM,例如:document.getElementById (未创建)
  79. */
  80. axios({
  81. method: "get",
  82. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=0',
  83. headers: {
  84. "Content-Type": "application/json"
  85. }
  86. }).then((res) => {
  87. this.courseList = res.data.data.result;
  88. })
  89. },
  90. mounted: function () {
  91. /* DOM对象已在页面上生成,此时就可以 */
  92. },
  93. template: `
  94. <div class="course-list">
  95. <div class="item" v-for="item in courseList">
  96. <router-link :to="{name:'Detail',params:{id:item.id}}">
  97. <img :src="item.cover" alt="">
  98. <a>{{item.name}}</a>
  99. </router-link>
  100. </div>
  101. </div>`
  102. }
  103. const News = {
  104. data: function () {
  105. return {
  106. dataList: []
  107. }
  108. },
  109. created: function () {
  110. /* 组件创建完成之后自动触发【此时组件的对象已创建,但还未将页面先关的DOM创建并显示在页面上】
  111. - 可以去操作组件对象,例如:this.courseList = [11,22,33]
  112. - 不可以去操作DOM,例如:document.getElementById (未创建)
  113. */
  114. axios({
  115. method: "get",
  116. url: 'https://api.luffycity.com/api/v1/course/actual/?limit=5&offset=10',
  117. headers: {
  118. "Content-Type": "application/json"
  119. }
  120. }).then((res) => {
  121. this.dataList = res.data.data.result;
  122. })
  123. },
  124. template: `<ul><li v-for="item in dataList">{{item.name}}</li></ul>`
  125. }
  126. const Detail = {
  127. data: function () {
  128. return {
  129. title: "详细页面",
  130. courseId: null,
  131. hotCourseList: [
  132. {id: 1000, title: "python全栈开发"},
  133. {id: 2000, title: "异步编程"},
  134. ],
  135. }
  136. },
  137. created: function () {
  138. this.courseId = this.$route.params.id;
  139. // 此处可以根据课程ID,发送ajax请求获取课程详细信息
  140. this.getCourseDetail();
  141. },
  142. watch: {
  143. $route: function (to, from) {
  144. this.courseId = to.params.id;
  145. this.getCourseDetail();
  146. }
  147. },
  148. methods: {
  149. getCourseDetail: function () {
  150. // 根据this.courseId获取课程详细信息
  151. }
  152. },
  153. template: `
  154. <div>
  155. <h2>课程详细页面</h2>
  156. <div>当前课程ID为:{{courseId}}</div>
  157. <h3>课程推荐</h3>
  158. <ul>
  159. <li v-for="item in hotCourseList">
  160. <router-link :to="{name:'Detail', params:{id:item.id}}">{{item.title}}</router-link>
  161. </li>
  162. </ul>
  163. </div>`
  164. }
  165. const Pins = {
  166. data: function () {
  167. return {}
  168. },
  169. template: `
  170. <div>
  171. <h2>沸点专区</h2>
  172. <router-link :to="{name:'Hot'}">热点</router-link>
  173. <router-link :to="{name:'Following'}">关注</router-link>
  174. //因为有了路由嵌套的关系 点击热点 组件是加载在这个router-view里,而不是全局的router-view
  175. <router-view></router-view>
  176. </div>
  177. `
  178. };
  179. const Hot = {template: `<div><h2>Hot页面</h2></div>`};
  180. const Following = {template: `<div><h2>Following页面</h2></div>`};
  181. const router = new VueRouter({
  182. routes: [
  183. {path: '/', component: Home},
  184. {path: '/home', component: Home},
  185. {path: '/course', component: Course},
  186. {path: '/news', component: News},
  187. {path: '/detail:id', component: Detail, name: 'Detail'},
  188. {
  189. path: '/pins',
  190. component: Pins,
  191. name: 'Pins',
  192. children: [
  193. {
  194. // 当 /pins/hot 匹配成功,
  195. // Hot组件 会被渲染在 Pins 的 <router-view> 中
  196. path: 'hot',
  197. component: Hot,
  198. name:'Hot'
  199. },
  200. {
  201. // 当 /pins/following 匹配成功,
  202. // Following组件 会被渲染在 Pins 的 <router-view> 中
  203. path: 'following',
  204. component: Following,
  205. name:'Following'
  206. }
  207. ]
  208. }
  209. ],
  210. //mode: 'history'
  211. })
  212. var app = new Vue({
  213. el: '#app',
  214. data: {},
  215. methods: {},
  216. router: router
  217. })
  218. </script>
  219. </body>
  220. </html>

案例:后台分类菜单

13.vue - 图7

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .header {
  11. height: 48px;
  12. background-color: #499ef3;
  13. line-height: 48px;
  14. }
  15. .header a {
  16. color: white;
  17. text-decoration: none;
  18. padding: 0 10px;
  19. }
  20. .body .left-menu {
  21. width: 180px;
  22. border: 1px solid #dddddd;
  23. border-bottom: 0;
  24. position: absolute;
  25. left: 1px;
  26. top: 50px;
  27. bottom: 0;
  28. overflow: auto;
  29. background-color: #f3f5f7;
  30. }
  31. .body .left-menu .head {
  32. border-bottom: 1px solid #dddddd;
  33. text-align: center;
  34. font-size: 18px;
  35. font-weight: bold;
  36. padding: 15px;
  37. }
  38. .body .left-menu a {
  39. display: block;
  40. padding: 10px;
  41. border-bottom: 1px solid #dddddd;
  42. }
  43. .body .right-body {
  44. position: absolute;
  45. left: 183px;
  46. top: 50px;
  47. right: 0;
  48. bottom: 0;
  49. overflow: auto;
  50. padding: 10px;
  51. }
  52. </style>
  53. <script src="vue.js"></script>
  54. <script src="vue-router.js"></script>
  55. <script src="axios.min.js"></script>
  56. </head>
  57. <body>
  58. <div id="app">
  59. <div class="header">
  60. <router-link to="/">Logo</router-link>
  61. <router-link to="/home">首页</router-link>
  62. <router-link to="/task">任务宝</router-link>
  63. <router-link to="/message">消息宝</router-link>
  64. </div>
  65. <div class="body">
  66. <router-view></router-view>
  67. </div>
  68. </div>
  69. <script>
  70. const Home = {
  71. data: function () {
  72. return {
  73. title: "欢迎使用xx系统"
  74. }
  75. },
  76. template: `<h2>{{title}}</h2>`
  77. };
  78. const Task = {
  79. data: function () {
  80. return {}
  81. },
  82. template: `
  83. <div>
  84. <div class="left-menu">
  85. <div class="head">任务宝</div>
  86. <router-link :to="{name:'Fans'}">粉丝</router-link>
  87. <router-link :to="{name:'Spread'}">推广码</router-link>
  88. <router-link :to="{name:'Statistics'}">数据统计</router-link>
  89. </div>
  90. <div class="right-body">
  91. <router-view></router-view>
  92. </div>
  93. </div>`
  94. };
  95. const Fans = {template: `<h3>粉丝页面</h3>`};
  96. const Spread = {template: `<h3>推广码页面</h3>`};
  97. const Statistics = {template: `<h3>数据统计页面</h3>`};
  98. const Message = {
  99. data: function () {
  100. return {}
  101. },
  102. template: `
  103. <div>
  104. <div class="left-menu">
  105. <div class="head">消息宝</div>
  106. <router-link :to="{name:'Sop'}">SOP</router-link>
  107. <router-link :to="{name:'Send'}">推送管理</router-link>
  108. </div>
  109. <div class="right-body">
  110. <router-view></router-view>
  111. </div>
  112. </div>`
  113. };
  114. const Sop = {template: `<h3>SOP页面</h3>`};
  115. const Send = {template: `<h3>推送管理页面</h3>`};
  116. const router = new VueRouter({
  117. routes: [
  118. {path: '/', component: Home},
  119. {path: '/home', component: Home},
  120. {
  121. path: '/task',
  122. component: Task,
  123. name: 'Task',
  124. children: [
  125. {
  126. path: '',
  127. // component: Fans,
  128. // redirect:'/task/fans'
  129. //重订向
  130. redirect: {name: 'Fans'}
  131. },
  132. {
  133. path: 'fans',
  134. component: Fans,
  135. name: 'Fans'
  136. },
  137. {
  138. path: 'spread',
  139. component: Spread,
  140. name: 'Spread'
  141. },
  142. {
  143. path: 'statistics',
  144. component: Statistics,
  145. name: 'Statistics'
  146. }
  147. ]
  148. },
  149. {
  150. path: '/message',
  151. component: Message,
  152. name: 'Message',
  153. children: [
  154. {
  155. path: 'sop',
  156. component: Sop,
  157. name: 'Sop'
  158. },
  159. {
  160. path: 'send',
  161. component: Send,
  162. name: 'Send'
  163. }
  164. ]
  165. }
  166. ]
  167. })
  168. var app = new Vue({
  169. el: '#app',
  170. data: {},
  171. methods: {},
  172. router: router
  173. })
  174. </script>
  175. </body>
  176. </html>

编程式导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

  • router.push

往history 栈添加元素 ,同时跳转过去

  1. // 字符串
  2. router.push('home')
  3. // 对象
  4. router.push({ path: 'home' })
  5. // 命名的路由 name就是路由里的name,并携带参数
  6. router.push({ name: 'user', params: { userId: '123' }}) //
  7. // 带查询参数,变成 /register?plan=private
  8. router.push({ path: 'register', query: { plan: 'private' }})
  • router.replace

把当前页面替换成某个页面

  1. // 字符串
  2. router.replace('home')
  3. // 对象
  4. router.replace({ path: 'home' })
  5. // 命名的路由
  6. router.replace({ name: 'user', params: { userId: '123' }})
  7. // 带查询参数,变成 /register?plan=private
  8. router.replace({ path: 'register', query: { plan: 'private' }})
  9. # router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
  • router.go 这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步
  1. // 在浏览器记录中前进一步,等同于 history.forward()
  2. router.go(1)
  3. // 后退一步记录,等同于 history.back()
  4. router.go(-1)
  5. // 前进 3 步记录
  6. router.go(3)
  7. // 如果 history 记录不够用,那就默默地失败呗
  8. router.go(-100)
  9. router.go(100)

案例:登录跳转(含顶部)

13.vue - 图8

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .header {
  11. height: 48px;
  12. background-color: #499ef3;
  13. line-height: 48px;
  14. }
  15. .header a {
  16. color: white;
  17. text-decoration: none;
  18. padding: 0 10px;
  19. }
  20. </style>
  21. <script src="vue.js"></script>
  22. <script src="vue-router.js"></script>
  23. </head>
  24. <body>
  25. <div id="app">
  26. <div class="header">
  27. <router-link to="/">Logo</router-link>
  28. <router-link to="/home">首页</router-link>
  29. <router-link to="/task">任务宝</router-link>
  30. <router-link to="/message">消息宝</router-link>
  31. <div style="float: right;">
  32. <router-link to="/login">登录</router-link>
  33. </div>
  34. </div>
  35. <div class="body">
  36. <router-view></router-view>
  37. </div>
  38. </div>
  39. <script>
  40. const Home = {
  41. data: function () {
  42. return {
  43. title: "欢迎使用xx系统"
  44. }
  45. },
  46. template: `<h2>{{title}}</h2>`
  47. };
  48. const Task = {
  49. data: function () {
  50. return {}
  51. },
  52. template: `
  53. <div>
  54. <h2>任务宝页面</h2>
  55. </div>`
  56. };
  57. const Message = {
  58. data: function () {
  59. return {}
  60. },
  61. template: `
  62. <div>
  63. <h2>消息宝页面</h2>
  64. </div>`
  65. };
  66. const Login = {
  67. data: function () {
  68. return {
  69. user: '',
  70. pwd: ''
  71. }
  72. },
  73. methods: {
  74. doLogin: function () {
  75. if (this.user.length > 0 && this.pwd.length > 0) {
  76. this.$router.push({name: 'Task'});
  77. // this.$router.replace({name: 'Task'});
  78. }
  79. }
  80. },
  81. template: `
  82. <div style="width: 500px;margin: 100px auto">
  83. <input type="text" placeholder="用户名" v-model="user"/>
  84. <input type="text" placeholder="密码" v-model="pwd" />
  85. <input type="button" value="提 交" @click="doLogin" />
  86. </div>
  87. `
  88. };
  89. const router = new VueRouter({
  90. routes: [
  91. {path: '/', component: Home},
  92. {path: '/home', component: Home},
  93. {path: '/login', component: Login, name: 'Login'},
  94. {path: '/task', component: Task, name: 'Task'},
  95. {path: '/message', component: Message, name: 'Message'}
  96. ]
  97. })
  98. var app = new Vue({
  99. el: '#app',
  100. data: {},
  101. methods: {},
  102. router: router
  103. })
  104. </script>
  105. </body>
  106. </html>

案例:登录跳转(不含顶部)

13.vue - 图9

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .header {
  11. height: 48px;
  12. background-color: #499ef3;
  13. line-height: 48px;
  14. }
  15. .header a {
  16. color: white;
  17. text-decoration: none;
  18. padding: 0 10px;
  19. }
  20. .body .left-menu {
  21. width: 180px;
  22. border: 1px solid #dddddd;
  23. border-bottom: 0;
  24. position: absolute;
  25. left: 1px;
  26. top: 50px;
  27. bottom: 0;
  28. overflow: auto;
  29. background-color: #f3f5f7;
  30. }
  31. .body .left-menu .head {
  32. border-bottom: 1px solid #dddddd;
  33. text-align: center;
  34. font-size: 18px;
  35. font-weight: bold;
  36. padding: 15px;
  37. }
  38. .body .left-menu a {
  39. display: block;
  40. padding: 10px;
  41. border-bottom: 1px solid #dddddd;
  42. }
  43. .body .right-body {
  44. position: absolute;
  45. left: 183px;
  46. top: 50px;
  47. right: 0;
  48. bottom: 0;
  49. overflow: auto;
  50. padding: 10px;
  51. }
  52. </style>
  53. <script src="vue.js"></script>
  54. <script src="vue-router.js"></script>
  55. </head>
  56. <body>
  57. <div id="app">
  58. <router-view></router-view>
  59. </div>
  60. <script>
  61. const Home = {
  62. data: function () {
  63. return {
  64. title: "欢迎使用xx系统"
  65. }
  66. },
  67. template: `
  68. <div>
  69. <div class="header">
  70. <router-link to="/">Logo</router-link>
  71. <router-link to="/home">首页</router-link>
  72. <router-link :to="{name:'Task'}">任务宝</router-link>
  73. <router-link :to="{name:'Message'}">消息宝</router-link>
  74. <div style="float: right;">
  75. <router-link to="/login">登录</router-link>
  76. </div>
  77. </div>
  78. <div class="body">
  79. <router-view></router-view>
  80. </div>
  81. </div>
  82. `
  83. };
  84. const Index = {template: '<h3>这是个首页呀...</h3>'}
  85. const Task = {
  86. data: function () {
  87. return {}
  88. },
  89. template: `
  90. <div>
  91. <div class="left-menu">
  92. <div class="head">任务宝</div>
  93. <router-link :to="{name:'Fans'}">粉丝</router-link>
  94. <router-link :to="{name:'Spread'}">推广码</router-link>
  95. <router-link :to="{name:'Statistics'}">数据统计</router-link>
  96. </div>
  97. <div class="right-body">
  98. <router-view></router-view>
  99. </div>
  100. </div>`
  101. };
  102. const Fans = {template: `<h3>粉丝页面</h3>`};
  103. const Spread = {template: `<h3>推广码页面</h3>`};
  104. const Statistics = {template: `<h3>数据统计页面</h3>`};
  105. const Message = {
  106. data: function () {
  107. return {}
  108. },
  109. template: `
  110. <div>
  111. <div class="left-menu">
  112. <div class="head">消息宝</div>
  113. <router-link :to="{name:'Sop'}">SOP</router-link>
  114. <router-link :to="{name:'Send'}">推送管理</router-link>
  115. </div>
  116. <div class="right-body">
  117. <router-view></router-view>
  118. </div>
  119. </div>`
  120. };
  121. const Sop = {template: `<h3>SOP页面</h3>`};
  122. const Send = {template: `<h3>推送管理页面</h3>`};
  123. const Login = {
  124. data: function () {
  125. return {
  126. user: '',
  127. pwd: ''
  128. }
  129. },
  130. methods: {
  131. doLogin: function () {
  132. if (this.user.length > 0 && this.pwd.length > 0) {
  133. this.$router.push({name: 'Index'});
  134. // this.$router.replace({name: 'Task'});
  135. }
  136. }
  137. },
  138. template: `
  139. <div style="width: 500px;margin: 100px auto">
  140. <input type="text" placeholder="用户名" v-model="user"/>
  141. <input type="text" placeholder="密码" v-model="pwd" />
  142. <input type="button" value="提 交" @click="doLogin" />
  143. </div>
  144. `
  145. };
  146. const router = new VueRouter({
  147. routes: [
  148. {
  149. path: '/',
  150. // component: Home,
  151. redirect: '/login'
  152. },
  153. {path: '/login', component: Login, name: 'Login'},
  154. {
  155. path: '/home',
  156. component: Home,
  157. children: [
  158. {
  159. path: '',
  160. component: Index,
  161. name: "Index"
  162. },
  163. {
  164. path: 'task',
  165. component: Task,
  166. name: 'Task',
  167. children: [
  168. {
  169. path: 'fans',
  170. component: Fans,
  171. name: 'Fans'
  172. },
  173. {
  174. path: 'spread',
  175. component: Spread,
  176. name: 'Spread'
  177. },
  178. {
  179. path: 'statistics',
  180. component: Statistics,
  181. name: 'Statistics'
  182. }
  183. ]
  184. },
  185. {
  186. path: 'message',
  187. component: Message,
  188. name: 'Message',
  189. children: [
  190. {
  191. path: 'sop',
  192. component: Sop,
  193. name: 'Sop'
  194. },
  195. {
  196. path: 'send',
  197. component: Send,
  198. name: 'Send'
  199. }
  200. ]
  201. }
  202. ],
  203. },
  204. ]
  205. })
  206. var app = new Vue({
  207. el: '#app',
  208. data: {},
  209. methods: {},
  210. router: router
  211. })
  212. </script>
  213. </body>
  214. </html>

导航守卫

在基于vue-router实现访问跳转时,都会执行一个钩子。

  1. const router = new VueRouter({ ... })
  2. # router.beforeEach 每个url执行之前
  3. router.beforeEach((to, from, next) => {
  4. // to: Route: 即将要进入的目标 路由对象
  5. // from: Route: 当前导航正要离开的路由
  6. // next() 继续向后执行
  7. // next(false) 中断导航,保持当前所在的页面。
  8. // next('/') next({path:'/'}) next({name:'Login'}) 跳转到指定页面
  9. })

注意:可以基于他实现未登录跳转登录页面。

案例:登录拦截(全局)

未登录时,访问后台管理页面,自动跳转到登录页面。

13.vue - 图10

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .header {
  11. height: 48px;
  12. background-color: #499ef3;
  13. line-height: 48px;
  14. }
  15. .header a {
  16. color: white;
  17. text-decoration: none;
  18. padding: 0 10px;
  19. }
  20. .body .left-menu {
  21. width: 180px;
  22. border: 1px solid #dddddd;
  23. border-bottom: 0;
  24. position: absolute;
  25. left: 1px;
  26. top: 50px;
  27. bottom: 0;
  28. overflow: auto;
  29. background-color: #f3f5f7;
  30. }
  31. .body .left-menu .head {
  32. border-bottom: 1px solid #dddddd;
  33. text-align: center;
  34. font-size: 18px;
  35. font-weight: bold;
  36. padding: 15px;
  37. }
  38. .body .left-menu a {
  39. display: block;
  40. padding: 10px;
  41. border-bottom: 1px solid #dddddd;
  42. }
  43. .body .right-body {
  44. position: absolute;
  45. left: 183px;
  46. top: 50px;
  47. right: 0;
  48. bottom: 0;
  49. overflow: auto;
  50. padding: 10px;
  51. }
  52. </style>
  53. <script src="vue.js"></script>
  54. <script src="vue-router.js"></script>
  55. </head>
  56. <body>
  57. <div id="app">
  58. <router-view></router-view>
  59. </div>
  60. <script>
  61. const Home = {
  62. data: function () {
  63. return {
  64. title: "欢迎使用xx系统"
  65. }
  66. },
  67. methods: {
  68. doLogout: function () {
  69. sessionStorage.clear();
  70. this.$router.push({name: "Login"});
  71. }
  72. },
  73. template: `
  74. <div>
  75. <div class="header">
  76. <router-link to="/">Logo</router-link>
  77. <router-link to="/home">首页</router-link>
  78. <router-link :to="{name:'Task'}">任务宝</router-link>
  79. <router-link :to="{name:'Message'}">消息宝</router-link>
  80. <div style="float: right;">
  81. <a @click="doLogout">注销</a>
  82. </div>
  83. </div>
  84. <div class="body">
  85. <router-view></router-view>
  86. </div>
  87. </div>
  88. `
  89. };
  90. const Index = {template: '<h3>这是个首页呀...</h3>'}
  91. const Task = {
  92. data: function () {
  93. return {}
  94. },
  95. template: `
  96. <div>
  97. <div class="left-menu">
  98. <div class="head">任务宝</div>
  99. <router-link :to="{name:'Fans'}">粉丝</router-link>
  100. <router-link :to="{name:'Spread'}">推广码</router-link>
  101. <router-link :to="{name:'Statistics'}">数据统计</router-link>
  102. </div>
  103. <div class="right-body">
  104. <router-view></router-view>
  105. </div>
  106. </div>`
  107. };
  108. const Fans = {template: `<h3>粉丝页面</h3>`};
  109. const Spread = {template: `<h3>推广码页面</h3>`};
  110. const Statistics = {template: `<h3>数据统计页面</h3>`};
  111. const Message = {
  112. data: function () {
  113. return {}
  114. },
  115. template: `
  116. <div>
  117. <div class="left-menu">
  118. <div class="head">消息宝</div>
  119. <router-link :to="{name:'Sop'}">SOP</router-link>
  120. <router-link :to="{name:'Send'}">推送管理</router-link>
  121. </div>
  122. <div class="right-body">
  123. <router-view></router-view>
  124. </div>
  125. </div>`
  126. };
  127. const Sop = {template: `<h3>SOP页面</h3>`};
  128. const Send = {template: `<h3>推送管理页面</h3>`};
  129. const Login = {
  130. data: function () {
  131. return {
  132. user: '',
  133. pwd: ''
  134. }
  135. },
  136. methods: {
  137. doLogin: function () {
  138. if (this.user.length > 0 && this.pwd.length > 0) {
  139. sessionStorage.setItem("isLogin", true);
  140. this.$router.push({name: 'Index'});
  141. }
  142. }
  143. },
  144. template: `
  145. <div style="width: 500px;margin: 100px auto">
  146. <input type="text" placeholder="用户名" v-model="user"/>
  147. <input type="text" placeholder="密码" v-model="pwd" />
  148. <input type="button" value="提 交" @click="doLogin" />
  149. </div>
  150. `
  151. };
  152. const router = new VueRouter({
  153. routes: [
  154. {
  155. path: '/',
  156. component: Home,
  157. redirect: '/home'
  158. },
  159. {
  160. path: '/home',
  161. component: Home,
  162. name: "Home",
  163. children: [
  164. {
  165. path: '',
  166. component: Index,
  167. name: "Index"
  168. },
  169. {
  170. path: 'task',
  171. component: Task,
  172. name: 'Task',
  173. children: [
  174. {
  175. path: 'fans',
  176. component: Fans,
  177. name: 'Fans'
  178. },
  179. {
  180. path: 'spread',
  181. component: Spread,
  182. name: 'Spread'
  183. },
  184. {
  185. path: 'statistics',
  186. component: Statistics,
  187. name: 'Statistics'
  188. }
  189. ]
  190. },
  191. {
  192. path: 'message',
  193. component: Message,
  194. name: 'Message',
  195. children: [
  196. {
  197. path: 'sop',
  198. component: Sop,
  199. name: 'Sop'
  200. },
  201. {
  202. path: 'send',
  203. component: Send,
  204. name: 'Send'
  205. }
  206. ]
  207. }
  208. ],
  209. },
  210. {path: '/login', component: Login, name: 'Login'},
  211. ]
  212. })
  213. router.beforeEach((to, from, next) => {
  214. // 如果已登录,则可以继续访问目标地址
  215. // sessionStorage存储到游览器上的一个值
  216. if (sessionStorage.getItem('isLogin')) {
  217. next();
  218. return;
  219. }
  220. // 未登录,访问登录页面
  221. if (to.name === "Login") {
  222. next();
  223. return;
  224. }
  225. // 未登录,跳转登录页面
  226. // next(false); 保持当前所在页面,不跳转
  227. next({name: 'Login'});
  228. })
  229. var app = new Vue({
  230. el: '#app',
  231. data: {},
  232. methods: {},
  233. router: router
  234. })
  235. </script>
  236. </body>
  237. </html>

案例:登录拦截(路由)

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. body {
  8. margin: 0;
  9. }
  10. .header {
  11. height: 48px;
  12. background-color: #499ef3;
  13. line-height: 48px;
  14. }
  15. .header a {
  16. color: white;
  17. text-decoration: none;
  18. padding: 0 10px;
  19. }
  20. .body .left-menu {
  21. width: 180px;
  22. border: 1px solid #dddddd;
  23. border-bottom: 0;
  24. position: absolute;
  25. left: 1px;
  26. top: 50px;
  27. bottom: 0;
  28. overflow: auto;
  29. background-color: #f3f5f7;
  30. }
  31. .body .left-menu .head {
  32. border-bottom: 1px solid #dddddd;
  33. text-align: center;
  34. font-size: 18px;
  35. font-weight: bold;
  36. padding: 15px;
  37. }
  38. .body .left-menu a {
  39. display: block;
  40. padding: 10px;
  41. border-bottom: 1px solid #dddddd;
  42. }
  43. .body .right-body {
  44. position: absolute;
  45. left: 183px;
  46. top: 50px;
  47. right: 0;
  48. bottom: 0;
  49. overflow: auto;
  50. padding: 10px;
  51. }
  52. </style>
  53. <script src="vue.js"></script>
  54. <script src="vue-router.js"></script>
  55. </head>
  56. <body>
  57. <div id="app">
  58. <router-view></router-view>
  59. </div>
  60. <script>
  61. const Home = {
  62. data: function () {
  63. return {
  64. title: "欢迎使用xx系统"
  65. }
  66. },
  67. methods: {
  68. doLogout: function () {
  69. sessionStorage.clear();
  70. this.$router.push({name: "Login"});
  71. }
  72. },
  73. template: `
  74. <div>
  75. <div class="header">
  76. <router-link to="/">Logo</router-link>
  77. <router-link to="/home">首页</router-link>
  78. <router-link :to="{name:'Task'}">任务宝</router-link>
  79. <router-link :to="{name:'Message'}">消息宝</router-link>
  80. <div style="float: right;">
  81. <a @click="doLogout">注销</a>
  82. </div>
  83. </div>
  84. <div class="body">
  85. <router-view></router-view>
  86. </div>
  87. </div>
  88. `
  89. };
  90. const Index = {template: '<h3>这是个首页呀...</h3>'}
  91. const Task = {
  92. data: function () {
  93. return {}
  94. },
  95. template: `
  96. <div>
  97. <div class="left-menu">
  98. <div class="head">任务宝</div>
  99. <router-link :to="{name:'Fans'}">粉丝</router-link>
  100. <router-link :to="{name:'Spread'}">推广码</router-link>
  101. <router-link :to="{name:'Statistics'}">数据统计</router-link>
  102. </div>
  103. <div class="right-body">
  104. <router-view></router-view>
  105. </div>
  106. </div>`
  107. };
  108. const Fans = {template: `<h3>粉丝页面</h3>`};
  109. const Spread = {template: `<h3>推广码页面</h3>`};
  110. const Statistics = {template: `<h3>数据统计页面</h3>`};
  111. const Message = {
  112. data: function () {
  113. return {}
  114. },
  115. template: `
  116. <div>
  117. <div class="left-menu">
  118. <div class="head">消息宝</div>
  119. <router-link :to="{name:'Sop'}">SOP</router-link>
  120. <router-link :to="{name:'Send'}">推送管理</router-link>
  121. </div>
  122. <div class="right-body">
  123. <router-view></router-view>
  124. </div>
  125. </div>`
  126. };
  127. const Sop = {template: `<h3>SOP页面</h3>`};
  128. const Send = {template: `<h3>推送管理页面</h3>`};
  129. const Login = {
  130. data: function () {
  131. return {
  132. user: '',
  133. pwd: ''
  134. }
  135. },
  136. methods: {
  137. doLogin: function () {
  138. if (this.user.length > 0 && this.pwd.length > 0) {
  139. sessionStorage.setItem("isLogin", true);
  140. this.$router.push({name: 'Index'});
  141. }
  142. }
  143. },
  144. template: `
  145. <div style="width: 500px;margin: 100px auto">
  146. <input type="text" placeholder="用户名" v-model="user"/>
  147. <input type="text" placeholder="密码" v-model="pwd" />
  148. <input type="button" value="提 交" @click="doLogin" />
  149. </div>
  150. `
  151. };
  152. const router = new VueRouter({
  153. routes: [
  154. {
  155. path: '/',
  156. component: Home,
  157. redirect: '/home'
  158. },
  159. {
  160. path: '/home',
  161. component: Home,
  162. name: "Home",
  163. children: [
  164. {
  165. path: '',
  166. component: Index,
  167. name: "Index"
  168. },
  169. {
  170. path: 'task',
  171. component: Task,
  172. name: 'Task',
  173. children: [
  174. {
  175. path: 'fans',
  176. component: Fans,
  177. name: 'Fans'
  178. },
  179. {
  180. path: 'spread',
  181. component: Spread,
  182. name: 'Spread'
  183. },
  184. {
  185. path: 'statistics',
  186. component: Statistics,
  187. name: 'Statistics'
  188. }
  189. ]
  190. },
  191. {
  192. path: 'message',
  193. component: Message,
  194. name: 'Message',
  195. children: [
  196. {
  197. path: 'sop',
  198. component: Sop,
  199. name: 'Sop'
  200. },
  201. {
  202. path: 'send',
  203. component: Send,
  204. name: 'Send'
  205. }
  206. ]
  207. }
  208. ],
  209. beforeEnter: (to, from, next) => {
  210. if (sessionStorage.getItem('isLogin')) {
  211. next();
  212. return;
  213. }
  214. // 未登录,跳转登录页面
  215. // next(false); 保持当前所在页面,不跳转
  216. next({name: 'Login'});
  217. }
  218. },
  219. {path: '/login', component: Login, name: 'Login'},
  220. ]
  221. })
  222. var app = new Vue({
  223. el: '#app',
  224. data: {},
  225. methods: {},
  226. router: router
  227. })
  228. </script>
  229. </body>
  230. </html>

补充:

  • cookie
  • localStorage
    1. setItem (key, value)
    2. getItem (key)
    3. removeItem (key)
    4. clear ()
    5. key (index)
  • sessionStorage

脚手架

基于vue+vue-router单文件开发,可以完成小规模的页面的开发,但如果项目大+组件多+依赖多,开发起来就非常不方便。

此时,脚手架(vue cli - Vue Command Line Interface )是一个基于 Vue.js 进行快速开发的完整系统。

  1. 官方的说法:
  2. Vue CLI 致力于将 Vue 生态中的工具基础标准化。它确保了各种构建工具能够基于智能的默认配置即可平稳衔接,这样你可以专注在撰写应用上,而不必花好几天去纠结配置的问题。
  1. 通俗的说法:
  2. 他帮助我们构内置了很多组件来帮助我们更便捷的的开发vue.js项目。

安装

  • 第一步:安装node.js ``` Vue CLI 4.x+ 需要 Node.js v8.9 或更高版本 (推荐 v10 以上)。

https://nodejs.org/en/download/

  1. <br />![](https://typora-image.obs.cn-north-4.myhuaweicloud.com/image/202205031736090.png#crop=0&crop=0&crop=1&crop=1&id=J3Qna&originHeight=136&originWidth=1336&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
  2. - 第二步:关于npm

安装上node之后,自带了npm包管理工具,类似于Python中的pip。

如果想要更新npm到最新版,可以执行命令: sudo npm install npm@latest -g

  1. <br />![](https://typora-image.obs.cn-north-4.myhuaweicloud.com/image/202205031736091.png#crop=0&crop=0&crop=1&crop=1&id=IxvbB&originHeight=152&originWidth=1292&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
  2. - 第三步:npm淘宝源,以后基于npm安装包就会快了(相当于豆瓣的pip源)

npm config set registry https://registry.npm.taobao.org

  1. - 第四步:全局安装vue-cli

安装(最新版)

sudo npm install -g @vue/cli

安装(指定版本)

sudo npm install -g @vue/cli@4.5.14

卸载

sudo npm uninstall -g @vue/cli

  1. <br />![](https://typora-image.obs.cn-north-4.myhuaweicloud.com/image/202205031736092.png#crop=0&crop=0&crop=1&crop=1&id=Qhc3C&originHeight=164&originWidth=1624&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title=)
  2. <a name="39da6755"></a>
  3. ## 创建项目
  4. ```javascript
  5. cd /Users/wupeiqi/WebstormProjects
  6. vue create mysite

13.vue - 图11

提示:babel是一个将ES6语法转化成ES5的工具,eslint是做语法检查。

13.vue - 图12

a few moments later…

13.vue - 图13

按照提示执行如下命令,脚手架就会给我们大家一个Web服务去运行编写的vue项目(便于开发测试)。

  1. cd mysite
  2. npm run serve

13.vue - 图14

13.vue - 图15

编译和部署

项目创建完,脚手架会默认会生成如下文件(包含项目依赖、配置文件、默认代码)。

13.vue - 图16

如果以后项目开发完毕,想要进行项目部署,是不需要这些文件的,执行命令:

  1. cd 项目目录
  2. npm run build

13.vue - 图17

build会将项目中的依赖和代码自动编译成HTML、CSS、JavaScript代码,后续只需要将此代码上传至服务器部署即可。

目录结构

  1. - babel.config.js babelES6转换ES5的组件,这是他所需的配置文件(一般不需要动)。
  2. - package.json 项目所需的包的版本信息。
  3. - package-lock.json 保存项目所需的包细节以及包的依赖等信息。
  4. - node-modules 项目安装依赖包的文件保存的地方。例如:npm install axios
  5. axios包会保存在此目录、信息也会写在 package.jsonpackage-lock.json
  6. - src
  7. - main.js 项目的启动 npm run serve ,用户访问时程序的入门。new vue()
  8. - App.vue 主组件
  9. - components 子组件
  10. - assets 静态文件(自己的静态文件,会被压缩和合并)
  11. - public 【此目录下的文件直接被复制到dist/目录下,一般放不动的数据,引入第三方】
  12. - index.html HTML文件(模板引擎)
  13. - favicon.icon 图标
  14. - README.md 项目说明文档

main.js

13.vue - 图18

render返回什么页面就看到什么,createElement是创建标签的

App.vue

13.vue - 图19

template 放html代码 script放js style放样式

  1. cd 项目
  2. npm install #会根据package-lock.json 自动下载所需要的包

本质上,其实就是将原来的代码做了拆分来进行开发,开发完毕之后再编译整合起来。

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
  7. </head>
  8. <body>
  9. <div id="app">
  10. <h1>欢迎学习Vue.js</h1>
  11. <div>我叫{{name}},微信{{wechat}}</div>
  12. </div>
  13. <script>
  14. var app = new Vue({
  15. el: '#app',
  16. data: {
  17. name: '武沛齐',
  18. wechat: 'wupeiqi888'
  19. },
  20. methods: {
  21. clickMe: function () {
  22. this.name = "alex";
  23. this.wechat = "wupeiqi666";
  24. }
  25. }
  26. })
  27. </script>
  28. </body>
  29. </html>

快速上手

13.vue - 图20

axios组件

安装:

  1. cd 项目目录
  2. npm install axios
  3. npm install vue-axios

导入:main.js文件中引入

  1. import Vue from 'vue'
  2. import axios from 'axios'
  3. import VueAxios from 'vue-axios'
  4. Vue.use(VueAxios, axios) #这两个组件挂载到vue中

使用:

  1. Vue.axios.get(api).then((response) => {
  2. console.log(response.data)
  3. })
  4. this.axios.get(api).then((response) => {
  5. console.log(response.data)
  6. })
  7. this.$http.get(api).then((response) => {
  8. console.log(response.data)
  9. })

vue-router组件

安装:

  1. cd 项目目录
  2. npm install vue-router@3

引入:

  1. // src/router/index.js
  2. import Vue from 'vue'
  3. import VueRouter from 'vue-router'
  4. import Home from '../components/Home'
  5. Vue.use(VueRouter)
  6. const router = new VueRouter({
  7. routes: [
  8. {
  9. path: '/home',
  10. name: "Home",
  11. component: Home
  12. },
  13. ]
  14. })
  15. export default router #导出router对象 外部就可以使用
  1. // main.js
  2. import Vue from 'vue'
  3. import axios from 'axios'
  4. import VueAxios from 'vue-axios'
  5. import App from './App.vue'
  6. // 导入router文件
  7. import router from "./router"
  8. Vue.use(VueAxios, axios)
  9. Vue.config.productionTip = true
  10. new Vue({
  11. router: router, #组件使用必须放在new Vue里
  12. render: h => h(App),
  13. }).$mount('#app')

使用:App.vue

  1. <template>
  2. <div>
  3. <router-link to="/home">点我</router-link>
  4. <router-view></router-view>
  5. </div>
  6. </template>

案例:路飞学城

基于vue-cli快速开发:路飞学城(第一版)

13.vue - 图21

线上部署

  • 第一步:编译
  1. npm run build
  • 第二步:将编译后的代码dist文件上传到服务器(阿里云、腾讯云)

13.vue - 图22

  • 第三步:安装nginx + 配置 + 启动
  1. yum install nginx
  1. vim /etc/nginx/nginx.conf
  2. user nginx;
  3. worker_processes auto;
  4. error_log /var/log/nginx/error.log;
  5. pid /run/nginx.pid;
  6. # Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
  7. include /usr/share/nginx/modules/*.conf;
  8. events {
  9. worker_connections 1024;
  10. }
  11. http {
  12. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  13. '$status $body_bytes_sent "$http_referer" '
  14. '"$http_user_agent" "$http_x_forwarded_for"';
  15. access_log /var/log/nginx/access.log main;
  16. sendfile on;
  17. tcp_nopush on;
  18. tcp_nodelay on;
  19. keepalive_timeout 65;
  20. types_hash_max_size 4096;
  21. include /etc/nginx/mime.types;
  22. default_type application/octet-stream;
  23. include /etc/nginx/conf.d/*.conf;
  24. server {
  25. listen 80;
  26. listen [::]:80;
  27. server_name _;
  28. # 项目目录
  29. root /data/mysite;
  30. # Load configuration files for the default server block.
  31. include /etc/nginx/default.d/*.conf;
  32. error_page 404 /404.html;
  33. location = /404.html {
  34. }
  35. error_page 500 502 503 504 /50x.html;
  36. location = /50x.html {
  37. }
  38. }
  39. }
  • 第四步:访问

vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

就是将组件中需要共享的数据交给vuex来帮我们进行管理,例如:用户登录状态、加入购物车。

13.vue - 图23

案例:登录

  1. vue create vxdemo
  2. npm install vue-router@3
  3. npm install vuex@3
  • main.js
  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import router from "./router"
  4. import store from "./store"
  5. Vue.config.productionTip = false
  6. new Vue({
  7. router: router,
  8. store: store, //store挂载到vue
  9. render: h => h(App),
  10. }).$mount('#app')
  • App.vue
  1. <template>
  2. <div id="app">
  3. <div class="menu">
  4. <div class="container">
  5. <router-link to="/home">首页</router-link>
  6. <router-link to="/course">课程</router-link>
  7. <div style="float: right">
  8. <a v-if="this.$store.state.isLogin">
  9. {{this.$store.state.userInfo.username}}
  10. </a>
  11. <router-link v-else to="/login">登录</router-link>
  12. </div>
  13. </div>
  14. </div>
  15. <div class="container">
  16. <router-view></router-view>
  17. </div>
  18. </div>
  19. </template>
  20. <script>
  21. export default {
  22. name: 'App',
  23. data() {
  24. return {}
  25. },
  26. components: {},
  27. }
  28. </script>
  29. <style>
  30. body {
  31. margin: 0;
  32. }
  33. .container {
  34. width: 1100px;
  35. margin: 0 auto;
  36. }
  37. .menu {
  38. height: 48px;
  39. background-color: #499ef3;
  40. line-height: 48px;
  41. }
  42. .menu a {
  43. color: white;
  44. text-decoration: none;
  45. padding: 0 10px;
  46. }
  47. </style>
  • src/store/index.js
  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. export default new Vuex.Store({
  5. //state存储数据的
  6. state: {
  7. isLogin: false, //是否登录
  8. userInfo: null //用户信息
  9. },
  10. //通过mutations中的函数来修改state中的值
  11. //state默认就是当前的,传过来的值在info
  12. mutations: {
  13. login: function (state, info) {
  14. state.userInfo = info;
  15. state.isLogin = true;
  16. },
  17. },
  18. actions: {}
  19. })
  • router/index.js
  1. // router/index.js
  2. import Vue from 'vue'
  3. import VueRouter from 'vue-router'
  4. import Home from '../components/Home'
  5. import Course from '../components/Course'
  6. import Login from '../components/Login'
  7. Vue.use(VueRouter)
  8. const router = new VueRouter({
  9. routes: [
  10. {
  11. path: '/home',
  12. name: "Home",
  13. component: Home
  14. },
  15. {
  16. path: '/course',
  17. name: "Course",
  18. component: Course
  19. },
  20. {
  21. path: '/login',
  22. name: "Login",
  23. component: Login
  24. },
  25. ]
  26. })
  27. export default router
  • components/Login.vue
  1. <template>
  2. <div>
  3. <input type="text" v-model="info.username" placeholder="用户名">
  4. <input type="password" v-model="info.password" placeholder="密码">
  5. <input type="button" value="登录" @click="doLogin"/>
  6. </div>
  7. </template>
  8. <script>
  9. export default {
  10. name: "Login",
  11. data() {
  12. return {
  13. info: {
  14. username: "",
  15. password: ""
  16. }
  17. }
  18. },
  19. methods: {
  20. doLogin: function () {
  21. // 1.用户登录
  22. this.$store.commit('login', this.info);
  23. // 2.登录成功修改状态
  24. this.$router.push({name: 'Home'});
  25. }
  26. }
  27. }
  28. </script>
  29. <style scoped>
  30. </style>

关于computed属性

在vue的组件中有一个computed属性(计算属性),监听关联的数据,如果发生变化则重新计算并显示。

  1. <template>
  2. <div>
  3. <h1>主页 {{v1}} {{ v2}}</h1>
  4. //{{totalData}} 是通过computed计算出来的,就是去读取computed中的totalData属性,并执行get方法,返回值放到此处
  5. <div>总数:{{totalData}}</div>
  6. <input type="button" value="点我" @click="addData"/>
  7. </div>
  8. </template>
  9. <script>
  10. export default {
  11. name: "Home",
  12. data() {
  13. return {
  14. v1: 123,
  15. v2: 456
  16. }
  17. },
  18. computed: {
  19. totalData: {
  20. get() {
  21. let data = this.v1 + this.v2;
  22. return data + 1000;
  23. },
  24. set(value) {
  25. this.v1 = value;
  26. }
  27. }
  28. },
  29. methods: {
  30. addData() {
  31. // 给totalData设置值的时候就会执行 set方法
  32. this.totalData = 999;
  33. // this.v2 = 1000;
  34. }
  35. }
  36. }
  37. </script>
  38. <style scoped>
  39. </style>

所以,上述案例也可以用computed属性来实现,例如:App.vue改成:

  1. <template>
  2. <div id="app">
  3. <div class="menu">
  4. <div class="container">
  5. <router-link to="/home">首页</router-link>
  6. <router-link to="/course">课程</router-link>
  7. <div style="float: right">
  8. <a v-if="userState">
  9. {{userName}}
  10. </a>
  11. <router-link v-else to="/login">登录</router-link>
  12. </div>
  13. </div>
  14. </div>
  15. <div class="container">
  16. <router-view></router-view>
  17. </div>
  18. </div>
  19. </template>
  20. <script>
  21. export default {
  22. name: 'App',
  23. data() {
  24. return {}
  25. },
  26. computed: {
  27. userState: {
  28. get() {
  29. return this.$store.state.isLogin;
  30. }
  31. },
  32. userName() {
  33. return this.$store.state.userInfo.username;
  34. },
  35. },
  36. components: {},
  37. }
  38. </script>
  39. <style>
  40. body {
  41. margin: 0;
  42. }
  43. .container {
  44. width: 1100px;
  45. margin: 0 auto;
  46. }
  47. .menu {
  48. height: 48px;
  49. background-color: #499ef3;
  50. line-height: 48px;
  51. }
  52. .menu a {
  53. color: white;
  54. text-decoration: none;
  55. padding: 0 10px;
  56. }
  57. </style>

案例:购物车

13.vue - 图24

  1. vue store存储commitdispatch
  2. this.$store.commit('toShowLoginDialog', true);
  3. this.$store.dispatch('toShowLoginDialog',false)
  4. 主要区别是:
  5. dispatch:含有异步操作,例如向后台提交数据,写法: this.$store.dispatch('mutations方法名',值)
  6. commit:同步操作,写法:this.$store.commit('mutations方法名',值)

关于Action

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

代码示例:

  1. const store = createStore({
  2. state: {
  3. count: 0
  4. },
  5. mutations: {
  6. increment (state) {
  7. state.count+=1;
  8. }
  9. },
  10. actions: {
  11. increment (context) {
  12. // 触发mutations
  13. context.commit('increment')
  14. }
  15. }
  16. })

在组件中如果要触发actions中的increment,则应该执行:

  1. this.$store.dispatch('increment')

这就有点像脱裤子放屁,意义何在呢? 当有异步操作时,应该使用action、而不是mutation,例如:

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. export default new Vuex.Store({
  5. state: {
  6. isLogin: false, //是否登录
  7. userInfo: null, //用户信息
  8. carNumber: 0,
  9. xxxxx: 10
  10. },
  11. mutations: {
  12. login: function (state, info) {
  13. state.userInfo = info;
  14. state.isLogin = true;
  15. },
  16. addCar: function (state) {
  17. state.carNumber += 1;
  18. },
  19. fetchAsync: function (state) {
  20. // ajax
  21. //setTimeout 1000毫秒以后才执行函数
  22. setTimeout(function () {
  23. state.xxxxx += 1;
  24. }, 1000);
  25. }
  26. },
  27. actions: {}
  28. })
  1. this.$store.commit("fetchAsync");

从效果上看是没有问题的,但是通过开发者工具就会发现,监测到的state的数据不准确。

13.vue - 图25

Action里面做异步操作,回调函数执行mutations,mutations里面修改state里面的值

所以,这种情况可以选择用Action。

  1. import Vue from 'vue'
  2. import Vuex from 'vuex'
  3. Vue.use(Vuex)
  4. export default new Vuex.Store({
  5. state: {
  6. isLogin: false, //是否登录
  7. userInfo: null, //用户信息
  8. carNumber: 0,
  9. xxxxx: 10
  10. },
  11. mutations: {
  12. login: function (state, info) {
  13. state.userInfo = info;
  14. state.isLogin = true;
  15. },
  16. addCar: function (state) {
  17. state.carNumber += 1;
  18. },
  19. fetchAsync: function (state,data) {
  20. state.xxxxx += 1;
  21. console.log(data);
  22. }
  23. },
  24. actions: {
  25. fetchAsync: function (context,data) {
  26. setTimeout(function () {
  27. context.commit("fetchAsync",data);
  28. }, 1000);
  29. }
  30. }
  31. })

再触发时,调用:

  1. this.$store.dispatch('fetchAsync',{ amount: 10})

flex布局

在CSS3中flex可以非常便捷的可以帮助我们实现对页面的布局。

  • 传统的页面布局,基于div+float来实现。
  • flex可以快速实现页面的布局(很方便)。

关于flex布局你必须要了解的有一下几点:

  1. <div class="menu" 样式>
  2. <div class="item" 样式>112</div>
  3. <div class="item">113</div>
  4. </div>

容器

flex布局

在容器元素上应用

  1. <div class="menu">
  2. <div class="item">112</div>
  3. <div class="item">113</div>
  4. </div>
  5. <style>
  6. .menu{
  7. border: 1px solid red;
  8. width: 500px;
  9. display: flex; // 表示flex布局
  10. }
  11. </style>

元素的方向(主轴和副轴)

  1. <div class="menu">
  2. <div class="item">112</div>
  3. <div class="item">113</div>
  4. </div>
  5. <style>
  6. .menu{
  7. border: 1px solid red;
  8. width: 500px;
  9. display: flex; // 表示flex布局
  10. flex-direction: row; // 主轴是横向,副轴是纵向。column
  11. }
  12. </style>

元素排列方式

  1. justify-content,主轴上的元素的排列方式
  2. align-items,副轴上的元素的排列方式。

13.vue - 图26

  1. <div class="menu">
  2. <div class="item">11</div>
  3. <div class="item">112</div>
  4. <div class="item">112</div>
  5. </div>
  6. <style>
  7. .menu {
  8. width: 500px;
  9. border: 1px solid red;
  10. display: flex;
  11. flex-direction: row;
  12. justify-content: flex-start; /* 主轴=横向,横向从左开始 */
  13. justify-content: flex-end; /* 主轴=横向,横向从右开始 */
  14. justify-content: space-between; /* 主轴=横向,左右定格,中间元素等分空白 */
  15. justify-content: space-around; /* 主轴=横向,所有元素等分空白 */
  16. justify-content: space-evenly; /* 主轴=横向,元素间距一样 */
  17. }
  18. .item {
  19. border: 1px solid green;
  20. padding: 5px 50px;
  21. height: 50px;
  22. width: 40px;
  23. }
  24. </style>

13.vue - 图27

  1. <div class="menu">
  2. <div class="item">11</div>
  3. <div class="item">112</div>
  4. <div class="item">112</div>
  5. </div>
  6. <style>
  7. .menu {
  8. width: 500px;
  9. height: 300px;
  10. border: 1px solid red;
  11. display: flex;
  12. flex-direction: row;
  13. justify-content: flex-start; /* 主轴=横向,横向从左开始 */
  14. justify-content: flex-end; /* 主轴=横向,横向从右开始 */
  15. justify-content: space-between; /* 主轴=横向,左右定格,中间元素等分空白 */
  16. justify-content: space-around; /* 主轴=横向,所有元素等分空白 */
  17. justify-content: space-evenly; /* 主轴=横向,元素间距一样 */
  18. align-items: center; /* 副轴=纵向,元素居中*/
  19. align-items: flex-start; /* 副轴=纵向,元素顶部*/
  20. align-items: flex-end; /* 副轴=纵向,元素底部*/
  21. }
  22. .item {
  23. border: 1px solid green;
  24. padding: 5px 50px;
  25. height: 50px;
  26. width: 40px;
  27. }
  28. </style>

换行

  • flex-wrap: nowrap; 元素超过容器,不换行
  • flex-wrap: wrap; 元素超过容器,换行

示例1:不换行

13.vue - 图28

  1. <div class="menu">
  2. <div class="item">11</div>
  3. <div class="item">112</div>
  4. <div class="item">112</div>
  5. <div class="item">112</div>
  6. <div class="item">112</div>
  7. </div>
  8. <style>
  9. .menu {
  10. width: 500px;
  11. height: 200px;
  12. border: 1px solid red;
  13. display: flex;
  14. flex-direction: row;
  15. justify-content: space-evenly; /* 主轴=横向,元素间距一样 */
  16. align-items: flex-start; /* 副轴=纵向,元素顶部*/
  17. flex-wrap: nowrap;
  18. }
  19. .item {
  20. border: 1px solid green;
  21. padding: 5px 50px;
  22. height: 50px;
  23. width: 40px;
  24. }
  25. </style>

示例2:换行

13.vue - 图29

  1. <div class="menu">
  2. <div class="item">111</div>
  3. <div class="item">112</div>
  4. <div class="item">112</div>
  5. <div class="item">112</div>
  6. <div class="item">112</div>
  7. </div>
  8. <style>
  9. body{
  10. margin: 0;
  11. }
  12. .menu {
  13. width: 500px;
  14. height: 200px;
  15. border: 1px solid red;
  16. display: flex;
  17. flex-direction: row;
  18. justify-content: space-evenly; /* 主轴=横向,元素间距一样 */
  19. align-items: flex-start; /* 副轴=纵向,元素顶部*/
  20. flex-wrap: wrap;
  21. }
  22. .item {
  23. border: 1px solid green;
  24. padding: 5px 50px;
  25. height: 50px;
  26. width: 40px;
  27. }
  28. </style>

多行对齐方式

align-content用于控制多行元素的对齐方式,如果元素只有一行则不会起作用;默认stretch,即在元素没设置高度,或高度为auto情况下让元素填满整个容器。

  1. flex-start | flex-end | center | space-between | space-around | space-evenly | stretch(默认);

元素

顺序

order,默认0,用于决定项目排列顺序,数值越小,项目排列越靠前。

13.vue - 图30

  1. <div class="father">
  2. <div class="son" style="order: 2">11</div>
  3. <div class="son" style="order: 0">22</div>
  4. <div class="son" style="order: 1">33</div>
  5. </div>
  6. <style scoped>
  7. .father {
  8. border: 1px solid red;
  9. width: 500px;
  10. height: 300px;
  11. display: flex;
  12. flex-direction: row;
  13. justify-content: flex-start;
  14. }
  15. .father .son {
  16. border: 1px solid saddlebrown;
  17. width: 20px;
  18. height: 18px;
  19. }
  20. </style>

剩余空间

flex-grow,默认0,用于决定项目在有剩余空间的情况下是否放大,默认不放大;

13.vue - 图31

  1. <div class="father">
  2. <div class="son">11</div>
  3. <div class="son" style="flex-grow: 1">22</div>
  4. <div class="son" style="flex-grow: 1">33</div>
  5. </div>

案例:flex页面布局

13.vue - 图32

  1. <template>
  2. <div>
  3. <div class="row1">
  4. <div class="company"></div>
  5. <div class="pic"></div>
  6. <div class="pic"></div>
  7. <div class="pic"></div>
  8. </div>
  9. <div class="row2">
  10. <div class="title">
  11. <div>手机</div>
  12. <div>查看更多</div>
  13. </div>
  14. <div class="pic-list">
  15. <div class="big"></div>
  16. <div class="right-list">
  17. <div class="group">
  18. <div class="phone"></div>
  19. <div class="phone"></div>
  20. <div class="phone"></div>
  21. <div class="phone"></div>
  22. </div>
  23. <div class="group">
  24. <div class="phone"></div>
  25. <div class="phone"></div>
  26. <div class="phone"></div>
  27. <div class="phone"></div>
  28. </div>
  29. </div>
  30. </div>
  31. </div>
  32. <div class="course-list">
  33. <div class="item"></div>
  34. <div class="item"></div>
  35. <div class="item"></div>
  36. <div class="item"></div>
  37. <div class="item"></div>
  38. </div>
  39. </div>
  40. </template>
  41. <script>
  42. export default {
  43. name: "Mi"
  44. }
  45. </script>
  46. <style scoped>
  47. .row1 {
  48. display: flex;
  49. flex-direction: row;
  50. justify-content: space-between;
  51. }
  52. .row1 .company {
  53. width: 210px;
  54. height: 180px;
  55. background-color: saddlebrown;
  56. }
  57. .row1 .pic {
  58. width: 266px;
  59. height: 180px;
  60. background-color: cadetblue;
  61. }
  62. .row2 .title {
  63. display: flex;
  64. flex-direction: row;
  65. justify-content: space-between;
  66. }
  67. .row2 .pic-list {
  68. display: flex;
  69. flex-direction: row;
  70. justify-content: space-between;
  71. }
  72. .row2 .pic-list .big {
  73. background-color: aquamarine;
  74. height: 610px;
  75. width: 210px;
  76. margin-right: 20px;
  77. }
  78. .row2 .pic-list .right-list {
  79. /*background-color: antiquewhite;*/
  80. flex-grow: 1;
  81. }
  82. .row2 .pic-list .right-list .group {
  83. display: flex;
  84. flex-direction: row;
  85. justify-content: space-between;
  86. flex-wrap: wrap;
  87. }
  88. .row2 .pic-list .right-list .phone {
  89. margin-bottom: 10px;
  90. border: 1px solid red;
  91. width: 200px;
  92. height: 300px;
  93. }
  94. .course-list {
  95. display: flex;
  96. justify-content: space-between;
  97. flex-wrap: wrap;
  98. }
  99. .course-list .item {
  100. width: 24%;
  101. height: 100px;
  102. background-color: skyblue;
  103. margin-top: 15px;
  104. }
  105. // 如果最后一个元素,是第3个,右边距=一个位置 + 所有空白位置/3(有三个空白位置)
  106. .course-list .item:last-child:nth-child(4n - 1) {
  107. margin-right: calc(24% + 4% / 3);
  108. }
  109. // 如果最后一个元素,是第2个,右边距=两个位置 + 所有空白位置/3*2(有三个空白位置)
  110. .course-list .item:last-child:nth-child(4n - 2) {
  111. margin-right: calc(48% + 8% / 3);
  112. }
  113. </style>

至此,结合以上的知识点,我们就可以来开发一个项目,但很多的页面按钮、标签、提示框等都需要自己手动,太费劲。

所以,接下来就要给大家的来聊一个UI框架 - ElementUI,他的内部提供了很多方便的样式和组件,可以加速我们开发。

ElementUI

Element,是有 饿了吗 团队开发一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的组件库(也支持vue3.x)。

在他的基础上来开发,可以大大提升开发进度。

13.vue - 图33

想要在项目中进行使用element-ui需要提前安装并引入。

引入

方式1:完整引入

  • 安装
    1. cd 项目目录
    2. npm install element-ui
  • 引入 ```javascript import Vue from ‘vue’; import ElementUI from ‘element-ui’; import ‘element-ui/lib/theme-chalk/index.css’; import App from ‘./App.vue’;

Vue.use(ElementUI);

new Vue({ render: h => h(App), }).$mount(‘#app’)

  1. - 在组件中使用
  2. ```html
  3. <el-button type="success">哈哈哈</el-button>

方式2:局部引入

  • 安装
    1. cd 项目目录
    2. npm install element-ui
  • 引入 ```javascript import Vue from ‘vue’; import { Button, Select } from ‘element-ui’; import ‘element-ui/lib/theme-chalk/index.css’; import App from ‘./App.vue’;

Vue.use(Button) Vue.use(Select)

new Vue({ render: h => h(App), }).$mount(‘#app’)

  1. - 在组件中使用
  2. ```html
  3. <el-button type="success">哈哈哈</el-button>


完整组件名称:https://element.eleme.cn/#/zh-CN/component/quickstart

组件的使用

参见官方文档,在后续的项目开发中来应用并使用。