本文目录
  1. Vue.js-01
    1. 课程介绍
      1. 什么是Vue.js
    2. 为什么要学习流行框架
    3. 框架和库的区别
    4. Node(后端)中的 MVC 与 前端中的 MVVM 之间的区别
    5. Vue.js 基本代码 和 MVVM 之间的对应关系
    6. v-cloak
    7. Vue指令之v-text和v-html
    8. Vue指令之v-bind的三种用法
    9. Vue指令之v-on和跑马灯效果
    10. Vue指令之v-on的缩写和事件修饰符
      1. 事件修饰符:
    11. Vue指令之v-model和双向数据绑定
    12. 简易计算器案例
    13. 在Vue中使用样式
      1. 使用class样式
      2. 使用内联样式
    14. Vue指令之v-for和key属性
    15. Vue指令之v-if和v-show
    16. Vue调试工具vue-devtools
    17. 过滤器
      1. 私有过滤器
      2. 全局过滤器
    18. 键盘修饰符以及自定义键盘修饰符
      1. 1.x中自定义键盘修饰符【了解即可】
      2. 2.x中自定义键盘修饰符
    19. 自定义指令
    20. 相关文章
  2. Vue.js-02
    1. 品牌管理案例
      1. 添加新品牌
      2. 删除品牌
      3. 根据条件筛选品牌
    2. vue-resource 实现 get, post, jsonp请求
      1. 使用动画钩子函数
      2. v-for 的列表过渡
      3. 列表的排序过渡
    3. 相关文章
  3. Vue.js-03
    1. 定义Vue组件
      1. 全局组件定义的三种方式
      2. 组件中展示数据和响应事件
      3. 【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象
      4. 使用components属性定义局部子组件
    2. 使用flag标识符结合v-if和v-else切换组件
    3. 子组件向父组件传值
  4. 这是一个大大的H1
  5. 登录组件
  6. 注册组件
    1. 设置路由高亮
    2. 设置路由切换动效
    3. 在路由规则中定义参数
    4. 使用 children 属性实现路由嵌套
    5. 命名视图实现经典布局
公告
淡泊明志,宁静致远
网站资讯
本站文章字数合计
282.8k
本站Hexo版本
6.1.0
本站Node版本
16.20.2
本站已运行时间
最后更新时间

分类: vue | 标签: vue vue-router

vue学习笔记

发表于: 2020-06-11 21:20:28 | 字数统计: 14.5k | 阅读时长预计: 72分钟

Vue.js-01

课程介绍

前5天: 都在学习Vue基本的语法和概念;打包工具 Webpack , Gulp
后5天: 以项目驱动教学;

什么是Vue.js

  • Vue.js 是目前最火的一个前端框架,React是最流行的一个前端框架(React除了开发网站,还可以开发手机App, Vue语法也是可以用于进行手机App开发的,需要借助于Weex)

  • Vue.js 是前端的主流框架之一,和Angular.js、React.js 一起,并成为前端三大主流框架!

  • Vue.js 是一套构建用户界面的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。(Vue有配套的第三方类库,可以整合起来做大型项目的开发)

  • 前端的主要工作?主要负责MVC中的V这一层;主要工作就是和界面打交道,来制作前端页面效果;

为什么要学习流行框架

  • 企业为了提高开发效率:在企业中,时间就是效率,效率就是金钱;
  • 企业中,使用框架,能够提高开发的效率;
  • 提高开发效率的发展历程:原生JS -> Jquery之类的类库 -> 前端模板引擎 -> Angular.js / Vue.js(能够帮助我们减少不必要的DOM操作;提高渲染效率;双向数据绑定的概念【通过框架提供的指令,我们前端程序员只需要关心数据的业务逻辑,不再关心DOM是如何渲染的了】)
  • 在Vue中,一个核心的概念,就是让用户不再操作DOM元素,解放了用户的双手,让程序员可以更多的时间去关注业务逻辑;

框架和库的区别

  • 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目。
  • node 中的 express;
  • 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。
    1. 从Jquery 切换到 Zepto
    1. 从 EJS 切换到 art-template

Node(后端)中的 MVC 与 前端中的 MVVM 之间的区别

  • MVC 是后端的分层开发概念;
  • MVVM是前端视图层的概念,主要关注于 视图层分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View , VM ViewModel
  • 为什么有了MVC还要有MVVM

01.MVC和MVVM的关系图解

Vue.js 基本代码 和 MVVM 之间的对应关系

 <div id="app">
        {{ msg }}
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                msg:"Hello Vue!"
            }
        })
    </script>

v-cloak

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        [v-clock]{
            display: none;
        }
    </style>
</head>
<body>
    <div id="app">
       <p v-clock> {{ msg }}</p>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                msg:"Hello Vue!"
            }
        })
    </script>
</body>
</html>

Vue指令之v-textv-html

 <div id="app">
       <div v-text="htmlStr"></div>
       <div v-html="htmlStr"></div>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                htmlStr:"<h2>我是h2</h2>"
            }
        })
    </script>

Vue指令之v-bind的三种用法

  1. 直接使用指令v-bind
  2. 使用简化指令:
  3. 在绑定的时候,拼接绑定内容::title="btnTitle + ', 这是追加的内容'"
    <div id="app">
      <button v-bind:title="msg">登录</button>
      <button :title="msg">登录</button>
      <button :title="btnTitle+'hello world'">登录</button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                msg:"你等着",
                btnTitle:"这是登录按钮提示信息"
            }
        })
    </script>

Vue指令之v-on跑马灯效果

<div id="app">
      <p>{{info}}</p>
      <button v-on:click="go">开始</button>
      <button @click="stop">停止</button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                info:"猥琐发育,别浪",
                intervalId:null
            },
            methods:{
                go(){
                    if(this.intervalId){return}
                    this.intervalId = setInterval(()=>{
                        this.info = this.info.substring(1)+this.info.substring(0,1);
                    },500)
                },
                stop(){
                    clearInterval(this.intervalId)
                    this.intervalId = null;
                }
            }
        })
    </script>

Vue指令之v-on的缩写事件修饰符

事件修饰符:

  • .stop 阻止冒泡

  • .prevent 阻止默认事件

  • .capture 添加事件侦听器时使用事件捕获模式

  • .self 只当事件在该元素本身(比如不是子元素)触发时触发回调

  • .once 事件只触发一次

<div id="app">
    <a @click.prevent='alert("阻止默认行为")' href="https://www.baidu.com">点我不会跳转</a>
</div>
<script src="./js/vue.js"></script>
<script>
    var vm = new Vue({
        el:"#app",
        data:{

        }
    })
</script>

Vue指令之v-model双向数据绑定

使用vue-devtools查看下面表单双向绑定效果:

    <div id="app">
      姓名:<input v-model="name"><br>
      性别:男:<input type="radio" v-model="gender" value="true">
            女:<input type="radio" v-model="gender" value="false"><br>
      爱好:篮球:<input type="checkbox" v-model="hobby" value="lanqiu">
           足球:  <input type="checkbox" v-model="hobby" value="zuqiu">
            排球: <input type="checkbox" v-model="hobby" value="paiqiu"><br>
      个人说明:<textarea cols="30" rows="10" v-model="desc"></textarea><br>
      民族:<select v-model="mingzu">
                <option value="hanzu">汉族</option>
                <option value="miaozu">苗族</option>
                <option value="weiwuerzu">维吾尔族</option>
                <option disabled value="">请选择民族</option>
            </select>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                name:'',
                gender:false,
                hobby:[],
                desc:'',
                mingzu:''
            }
        })
    </script>

简易计算器案例

  1. HTML 代码结构

  <div id="app">

    <input type="text" v-model="n1">

    <select v-model="opt">

      <option value="0">+</option>

      <option value="1">-</option>

      <option value="2">*</option>

      <option value="3">÷</option>

    </select>

    <input type="text" v-model="n2">

    <input type="button" value="=" v-on:click="getResult">

    <input type="text" v-model="result">

  </div>
  1. Vue实例代码:

    // 创建 Vue 实例,得到 ViewModel

    var vm = new Vue({

      el: '#app',

      data: {

        n1: 0,

        n2: 0,

        result: 0,

        opt: '0'

      },

      methods: {

        getResult() {

          switch (this.opt) {

            case '0':

              this.result = parseInt(this.n1) + parseInt(this.n2);

              break;

            case '1':

              this.result = parseInt(this.n1) - parseInt(this.n2);

              break;

            case '2':

              this.result = parseInt(this.n1) * parseInt(this.n2);

              break;

            case '3':

              this.result = parseInt(this.n1) / parseInt(this.n2);

              break;

          }

        }

      }

    });

在Vue中使用样式

使用class样式

  1. 数组

    <h1 :class="['red', 'thin']">这是一个邪恶的H1</h1>
    
  2. 数组中使用三元表达式

    <h1 :class="['red', 'thin', isactive?'active':'']">这是一个邪恶的H1</h1>
    
  3. 数组中嵌套对象

    <h1 :class="['red', 'thin', {'active': isactive}]">这是一个邪恶的H1</h1>
    
  4. 直接使用对象

    <h1 :class="{red:true, italic:true, active:true, thin:true}">这是一个邪恶的H1</h1>
    

案例:

<div id="app">
        <h1 :class="['red','thin']">使用数组添加样式</h1>
        <h1 :class="['red','thin',isactive?'active':'']">使用三元表达式添加样式</h1>
        <h1 :class="['red','thin',{'active':isactive}]">数组中嵌套对象添加样式</h1>
        <h1 :class="{red:true,thin:false}">直接使用对象添加样式</h1>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                isactive:true
            }
        })
    </script>

使用内联样式

  1. 直接在元素上通过 :style 的形式,书写样式对象

    <h1 :style="{color: 'red', 'font-size': '40px'}">这是一个善良的H1</h1>
    
  2. 将样式对象,定义到 data 中,并直接引用到 :style

  • 在data上定义样式:
    data: {
         h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
    }
    
  • 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
    <h1 :style="h1StyleObj">这是一个善良的H1</h1>
    
  1. :style 中通过数组,引用多个 data 上的样式对象
  • 在data上定义样式:
    data: {
         h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },
         h1StyleObj2: { fontStyle: 'italic' }
    }
    
  • 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
    <h1 :style="[h1StyleObj, h1StyleObj2]">这是一个善良的H1</h1>
    

Vue指令之v-forkey属性

  1. 迭代数组(注意加上:key)
<ul>
  <li v-for="(item, i) in list" :key="item.id">索引:{{i}} --- 姓名:{{item.name}} --- 年龄:{{item.age}}</li>
</ul>
  1. 迭代对象中的属性

    <!-- 循环遍历对象身上的属性 -->

    <div v-for="(val, key, i) in userInfo">{{val}} --- {{key}} --- {{i}}</div>
  1. 迭代数字

<p v-for="i in 10">这是第 {{i}} 个P标签</p>

2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的。

当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

Vue指令之v-ifv-show

一般来说,v-if 有更高的切换消耗而 v-show 有更高的初始渲染消耗。因此,如果需要频繁切换 v-show 较好,如果在运行时条件不大可能改变 v-if 较好。

<div id="app">
        <p v-if="sceen">我是v-if</p>
        <p v-show="sceen">我是v-show</p>
        <button @click="toggle">切换</button>
    </div>
    <script src="./js/vue.js"></script>
    <script>
        var vm = new Vue({
            el:"#app",
            data:{
                sceen:false
            },
            methods:{
                toggle(){
                    this.sceen = !this.sceen;
                }
            }
        })
  1. 在2.x版本中手动实现筛选的方式
  • 筛选框绑定到 VM 实例中的 searchName 属性:

<hr> 输入筛选名称:

<input type="text" v-model="searchName">
  • 在使用 v-for 指令循环每一行数据的时候,不再直接 item in list,而是 in 一个 过滤的methods 方法,同时,把过滤条件searchName传递进去:

<tbody>

      <tr v-for="item in search(searchName)">

        <td>{{item.id}}</td>

        <td>{{item.name}}</td>

        <td>{{item.ctime}}</td>

        <td>

          <a href="#" @click.prevent="del(item.id)">删除</a>

        </td>

      </tr>

    </tbody>
  • search 过滤方法中,使用 数组的 filter 方法进行过滤:

search(name) {

  return this.list.filter(x => {

    return x.name.indexOf(name) != -1;

  });

}

Vue调试工具vue-devtools

过滤器

概念:Vue.js 允许你自定义过滤器,可被用作一些常见的文本格式化。过滤器可以用在两个地方:mustache 插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;

私有过滤器

  1. HTML元素:

<td>{{item.ctime | dataFormat('yyyy-mm-dd')}}</td>
  1. 私有 filters 定义方式:

filters: { // 私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用

    dataFormat(input, pattern = "") { // 在参数列表中 通过 pattern="" 来指定形参默认值,防止报错

      var dt = new Date(input);

      // 获取年月日

      var y = dt.getFullYear();

      var m = (dt.getMonth() + 1).toString().padStart(2, '0');

      var d = dt.getDate().toString().padStart(2, '0');



      // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日

      // 否则,就返回  年-月-日 时:分:秒

      if (pattern.toLowerCase() === 'yyyy-mm-dd') {

        return `${y}-${m}-${d}`;

      } else {

        // 获取时分秒

        var hh = dt.getHours().toString().padStart(2, '0');

        var mm = dt.getMinutes().toString().padStart(2, '0');

        var ss = dt.getSeconds().toString().padStart(2, '0');



        return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;

      }

    }

  }

使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString=’’) 或 String.prototype.padEnd(maxLength, fillString=’’)来填充字符串;

全局过滤器


// 定义一个全局过滤器,注意全局过滤器要写在new Vue()之前,否则会报错

Vue.filter('dataFormat', function (input, pattern = '') {

  var dt = new Date(input);

  // 获取年月日

  var y = dt.getFullYear();

  var m = (dt.getMonth() + 1).toString().padStart(2, '0');

  var d = dt.getDate().toString().padStart(2, '0');



  // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日

  // 否则,就返回  年-月-日 时:分:秒

  if (pattern.toLowerCase() === 'yyyy-mm-dd') {

    return `${y}-${m}-${d}`;

  } else {

    // 获取时分秒

    var hh = dt.getHours().toString().padStart(2, '0');

    var mm = dt.getMinutes().toString().padStart(2, '0');

    var ss = dt.getSeconds().toString().padStart(2, '0');



    return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;

  }

});

注意:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!

键盘修饰符以及自定义键盘修饰符

1.x中自定义键盘修饰符【了解即可】


Vue.directive('on').keyCodes.f2 = 113;

2.x中自定义键盘修饰符

  1. 通过Vue.config.keyCodes.名称 = 按键值来自定义案件修饰符的别名:

Vue.config.keyCodes.f2 = 113;
  1. 使用自定义的按键修饰符:

<input type="text" v-model="name" @keyup.f2="add">

自定义指令

  1. 自定义全局和局部的 自定义指令:

    // 自定义全局指令 v-focus,为绑定的元素自动获取焦点:

    Vue.directive('focus', {

      inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用

        el.focus();

      }

    });



    // 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细:

      directives: {

        color: { // 为元素设置指定的字体颜色

          bind(el, binding) {

            el.style.color = binding.value;

          }

        },

        'font-weight': function (el, binding2) { // 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数

          el.style.fontWeight = binding2.value;

        }

      }
  1. 自定义指令的使用方式:

<input type="text" v-model="searchName" v-focus v-color="'red'" v-font-weight="900">

相关文章

  1. vue.js 1.x 文档
  2. vue.js 2.x 文档
  3. String.prototype.padStart(maxLength, fillString)
  4. js 里面的键盘事件对应的键码
  5. Vue.js双向绑定的实现原理

Vue.js-02

品牌管理案例

添加新品牌

删除品牌

根据条件筛选品牌

  1. 1.x 版本中的filterBy指令,在2.x中已经被废除:

filterBy - 指令


<tr v-for="item in list | filterBy searchName in 'name'">

  <td>{{item.id}}</td>

  <td>{{item.name}}</td>

  <td>{{item.ctime}}</td>

  <td>

    <a href="#" @click.prevent="del(item.id)">删除</a>

  </td>

</tr>
  1. 在2.x版本中手动实现筛选的方式
  • 筛选框绑定到 VM 实例中的 searchName 属性:

<hr> 输入筛选名称:

<input type="text" v-model="searchName">
  • 在使用 v-for 指令循环每一行数据的时候,不再直接 item in list,而是 in 一个 过滤的methods 方法,同时,把过滤条件searchName传递进去:

<tbody>

      <tr v-for="item in search(searchName)">

        <td>{{item.id}}</td>

        <td>{{item.name}}</td>

        <td>{{item.ctime}}</td>

        <td>

          <a href="#" @click.prevent="del(item.id)">删除</a>

        </td>

      </tr>

    </tbody>
  • search 过滤方法中,使用 数组的 filter 方法进行过滤:

search(name) {

  return this.list.filter(x => {

    return x.name.indexOf(name) != -1;

  });

}

vue实例的生命周期

  • 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
  • 生命周期钩子:就是生命周期事件的别名而已;
  • 生命周期钩子 = 生命周期函数 = 生命周期事件
  • 主要的生命周期函数分类:
  • 创建期间的生命周期函数:

    • beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
    • created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
    • beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
    • mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
  • 运行期间的生命周期函数:

    • beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
    • updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
  • 销毁期间的生命周期函数:

    • beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
    • destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

lifecycle

【生命周期案例】

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div id="app">
        <h2 id="h2">{{msg}}</h2>
        <button @click="msg = 'no'">改变数据</button>
    </div>
   <script src="./js/vue.js"></script>
   <script>
       var vm = new Vue({
            el:"#app",
            data:{
               msg:"yes"
            },
            methods:{
                show(){
                    console.log('这是show方法');
                }
            },
            beforeCreate(){
                //此时data和methods还没初始化
                //console.log(this.msg);//undefined
                //console.log(this.show());
            },
            created(){
                //此时data和methods已经初始化
                // console.log(this.msg);
                // this.show()
            },
            beforeMount(){
                //此时已经在内存中编译好了模板,只是还未同步到页面
                // console.log("页面中:"+document.getElementById("h2").innerText);//{{msg}}
                // console.log("data中:"+this.msg);//yes
            },
            mounted(){
                //此时已经将编译好的模板同步到页面了,标识vue创建阶段完毕,进入运行阶段
                // console.log("页面中:"+document.getElementById("h2").innerText);//yes
                // console.log("data中:"+this.msg);//yes
            },
            beforeUpdate(){
                //当数据改变调用此方法,但数据还未与页面同步
                // console.log("页面中:"+document.getElementById("h2").innerText);//yes
                // console.log("data中:"+this.msg);//no
            },
            updated(){
                //此时页面和数据已经同步
                // console.log("页面中:"+document.getElementById("h2").innerText);//yes
                // console.log("data中:"+this.msg);//yes
            }
       });
   </script>
</body>
</html>

vue-resource 实现 get, post, jsonp请求

除了 vue-resource 之外,还可以使用 axios 的第三方包实现实现数据的请求

  1. 之前的学习中,如何发起数据请求?
  2. 常见的数据请求类型? get post jsonp
  3. 测试的URL请求资源地址:
  1. JSONP的实现原理
  • 由于浏览器的安全性限制,不允许AJAX访问 协议不同、域名不同、端口号不同的 数据接口,浏览器认为这种访问不安全;

  • 可以通过动态创建script标签的形式,把script标签的src属性,指向数据接口的地址,因为script标签不存在跨域限制,这种数据获取方式,称作JSONP(注意:根据JSONP的实现原理,知晓,JSONP只支持Get请求);

  • 具体实现过程:

    • 先在客户端定义一个回调方法,预定义对数据的操作;
    • 再把这个回调方法的名称,通过URL传参的形式,提交到服务器的数据接口;
    • 服务器数据接口组织好要发送给客户端的数据,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行;
    • 客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能够拿到JSONP的数据了;
  • 带大家通过 Node.js ,来手动实现一个JSONP的请求例子;
    ```
    const http = require(‘http’);
    // 导入解析 URL 地址的核心模块
    const urlModule = require(‘url’);

    const server = http.createServer();
    // 监听 服务器的 request 请求事件,处理每个请求
    server.on(‘request’, (req, res) => {
    const url = req.url;

    // 解析客户端请求的URL地址
    var info = urlModule.parse(url, true);

    // 如果请求的 URL 地址是 /getjsonp ,则表示要获取JSONP类型的数据
    if (info.pathname === ‘/getjsonp’) {
    // 获取客户端指定的回调函数的名称
    var cbName = info.query.callback;
    // 手动拼接要返回给客户端的数据对象
    var data = {
    name: ‘zs’,
    age: 22,
    gender: ‘男’,
    hobby: [‘吃饭’, ‘睡觉’, ‘运动’]
    }
    // 拼接出一个方法的调用,在调用这个方法的时候,把要发送给客户端的数据,序列化为字符串,作为参数传递给这个调用的方法:
    var result = ${cbName}(${JSON.stringify(data)});
    // 将拼接好的方法的调用,返回给客户端去解析执行
    res.end(result);
    } else {
    res.end(‘404’);
    }
    });

    server.listen(3000, () => {
    console.log(‘server running at http://127.0.0.1:3000');
    });

5. vue-resource 的配置步骤:
+ 直接在页面中,通过`script`标签,引入 `vue-resource` 的脚本文件;
+ 注意:引用的先后顺序是:先引用 `Vue` 的脚本文件,再引用 `vue-resource` 的脚本文件;
6. 发送get请求:

getInfo() { // get 方式获取数据
this.$http.get(‘http://127.0.0.1:8899/api/getlunbo').then(res => {
console.log(res.body);
})
}

7. 发送post请求:

postInfo() {
var url = ‘http://127.0.0.1:8899/api/post';
// post 方法接收三个参数:
// 参数1: 要请求的URL地址
// 参数2: 要发送的数据对象
// 参数3: 指定post提交的编码类型为 application/x-www-form-urlencoded
this.$http.post(url, { name: ‘zs’ }, { emulateJSON: true }).then(res => {
console.log(res.body);
});
}

8. 发送JSONP请求获取数据:

jsonpInfo() { // JSONP形式从服务器获取数据
var url = ‘http://127.0.0.1:8899/api/jsonp';
this.$http.jsonp(url).then(res => {
console.log(res.body);
});
}


## 配置本地数据库和数据接口API
1. 先解压安装 `PHPStudy`;
2. 解压安装 `Navicat` 这个数据库可视化工具,并激活;
3. 打开 `Navicat` 工具,新建空白数据库,名为 `dtcmsdb4`;
4. 双击新建的数据库,连接上这个空白数据库,在新建的数据库上`右键` -> `运行SQL文件`,选择并执行 `dtcmsdb4.sql` 这个数据库脚本文件;如果执行不报错,则数据库导入完成;
5. 进入文件夹 `vuecms3_nodejsapi` 内部,执行 `npm i` 安装所有的依赖项;
6. 先确保本机安装了 `nodemon`, 没有安装,则运行 `npm i nodemon -g` 进行全局安装,安装完毕后,进入到 `vuecms3_nodejsapi`目录 -> `src`目录 -> 双击运行 `start.bat`
7. 如果API启动失败,请检查 PHPStudy 是否正常开启,同时,检查 `app.js` 中第 `14行` 中数据库连接配置字符串是否正确;PHPStudy 中默认的 用户名是root,默认的密码也是root

## 品牌管理改造
### 展示品牌列表

### 添加品牌数据

### 删除品牌数据

## [Vue中的动画](https://cn.vuejs.org/v2/guide/transitions.html)
为什么要有动画:动画能够提高用户的体验,帮助用户更好的理解页面中的功能;

### 使用过渡类名
1. HTML结构:
动画哦
``` 2. VM 实例: ``` // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { isshow: false }, methods: { myAnimate() { this.isshow = !this.isshow; } } }); ``` 3. 定义两组类样式: ``` /* 定义进入和离开时候的过渡状态 */ .fade-enter-active, .fade-leave-active { transition: all 0.2s ease; position: absolute; }
/* 定义进入过渡的开始状态 和 离开过渡的结束状态 */
.fade-enter,
.fade-leave-to {
  opacity: 0;
  transform: translateX(100px);
}

### [使用第三方 CSS 动画库](https://cn.vuejs.org/v2/guide/transitions.html#自定义过渡类名)
1. 导入动画类库:
``` 2. 定义 transition 及属性: ```
动画哦
```

使用动画钩子函数

  1. 定义 transition 组件以及三个钩子函数:
    <div id="app">
     <input type="button" value="切换动画" @click="isshow = !isshow">
     <transition
     @before-enter="beforeEnter"
     @enter="enter"
     @after-enter="afterEnter">
       <div v-if="isshow" class="show">OK</div>
     </transition>
      </div>
    
  2. 定义三个 methods 钩子方法:
    methods: {
         beforeEnter(el) { // 动画进入之前的回调
           el.style.transform = 'translateX(500px)';
         },
         enter(el, done) { // 动画进入完成时候的回调
           el.offsetWidth;
           el.style.transform = 'translateX(0px)';
           done();
         },
         afterEnter(el) { // 动画进入完成之后的回调
           this.isshow = !this.isshow;
         }
       }
    
  3. 定义动画过渡时长和样式:
    .show{
       transition: all 0.4s ease;
     }
    

v-for 的列表过渡

  1. 定义过渡样式:
    ```

    2. 定义DOM结构,其中,需要使用 transition-group 组件把v-for循环的列表包裹起来:
    
    <transition-group tag="ul" name="list">
      <li v-for="(item, i) in list" :key="i">{{item}}</li>
    </transition-group>
    
    ``` 3. 定义 VM中的结构: ``` // 创建 Vue 实例,得到 ViewModel var vm = new Vue({ el: '#app', data: { txt: '', list: [1, 2, 3, 4] }, methods: { add() { this.list.push(this.txt); this.txt = ''; } } }); ```

    列表的排序过渡

    <transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用

    • v-movev-leave-active 结合使用,能够让列表的过渡更加平缓柔和:
      .v-move{
      transition: all 0.8s ease;
      }
      .v-leave-active{
      position: absolute;
      }
      

    相关文章

    1. vue.js 1.x 文档
    2. vue.js 2.x 文档
    3. String.prototype.padStart(maxLength, fillString)
    4. js 里面的键盘事件对应的键码
    5. pagekit/vue-resource
    6. navicat如何导入sql文件和导出sql文件
    7. 贝塞尔在线生成器

    Vue.js-03

    定义Vue组件

    什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
    组件化和模块化的不同:

    • 模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
    • 组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;

      全局组件定义的三种方式

    1. 使用 Vue.extend 配合 Vue.component 方法:
      var login = Vue.extend({
         template: '<h1>登录</h1>'
       });
       Vue.component('login', login);
      
    2. 直接使用 Vue.component 方法:
      Vue.component('register', {
         template: '<h1>注册</h1>'
       });
      
    3. 将模板字符串,定义到script标签种:
      <script id="tmpl" type="x-template">
         <div><a href="#">登录</a> | <a href="#">注册</a></div>
       </script>
      
      同时,需要使用 Vue.component 来定义组件:
      Vue.component('account', {
         template: '#tmpl'
       });
      

    注意: 组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!

    组件中展示数据和响应事件

    1. 在组件中,data需要被定义为一个方法,例如:
      Vue.component('account', {
         template: '#tmpl',
         data() {
           return {
             msg: '大家好!'
           }
         },
         methods:{
           login(){
             alert('点击了登录按钮');
           }
         }
       });
      
    2. 在子组件中,如果将模板字符串,定义到了script标签中,那么,要访问子组件身上的data属性中的值,需要使用this来访问;

    【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象

    1. 通过计数器案例演示
    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
      </head>
      <body>
        <div id="app">
          <counter></counter>
          <hr>
          <counter></counter>
          <hr>
          <counter></counter>
        </div>
    
        <!-- 定义模板 -->
        <template id="tmpl">
          <div>
            <h2>{{count}}</h2>
            <button type="button" @click="increment">+1</button>
          </div>
        </template>
    
        <script src="./js/vue.js"></script>
        
        <script>
          // var dataObj = {count:0}
          Vue.component("counter",{
            template:"#tmpl",
            data(){
              return {count:0};
            },
            methods:{
              increment(){
                this.count++;
              }
            }
          })
          
          var vm = new Vue({
            el: "#app"
          });
        </script>
      </body>
    </html>
    

    使用components属性定义局部子组件

    1. 组件实例定义方式:
      <script>
       // 创建 Vue 实例,得到 ViewModel
       var vm = new Vue({
         el: '#app',
         data: {},
         methods: {},
         components: { // 定义子组件
           account: { // account 组件
             template: '<div><h1>这是Account组件{{name}}</h1><login></login></div>', // 在这里使用定义的子组件
             components: { // 定义子组件的子组件
               login: { // login 组件
                 template: "<h3>这是登录组件</h3>"
               }
             }
           }
         }
       });
        </script>
      
    2. 引用组件:
      <div id="app">
       <account></account>
        </div>
      

    使用flag标识符结合v-ifv-else切换组件

    1. 页面结构:
      <div id="app">
       <input type="button" value="toggle" @click="flag=!flag">
       <!-- 组件名称定义为驼峰时,标签要用-分开 -->
       <my-com1 v-if="flag"></my-com1>
       <my-com2 v-else="flag"></my-com2>
        </div>
      
    2. Vue实例定义:
      ```js

      
      ## 使用`:is`属性来切换不同的子组件,并添加切换动画
      1. 组件实例定义方式:
      

      // 登录组件
      const login = Vue.extend({
      template: <div> <h3>登录组件</h3> </div>
      });
      Vue.component(‘login’, login);

      // 注册组件
      const register = Vue.extend({
        template: `<div>
          <h3>注册组件</h3>
        </div>`
      });
      Vue.component('register', register);
      
      // 创建 Vue 实例,得到 ViewModel
      var vm = new Vue({
        el: '#app',
        data: { comName: 'login' },
        methods: {}
      });
      
      2. 使用`component`标签,来引用组件,并通过`:is`属性来指定要加载的组件:
      
      ``` 3. 添加切换样式: ```

      
      ## 父组件向子组件传值
      1. 组件实例定义方式,注意:一定要使用`props`属性来定义父组件传递过来的数据
      
      2. 使用`v-bind`或简化指令,将数据传递到子组件中:
      
      ```

      子组件向父组件传值

      1. 原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去;
      2. 父组件将方法的引用传递给子组件,其中,getMsg是父组件中methods中定义的方法名称,func是子组件调用传递过来方法时候的方法名称
        <son @func="getMsg"></son>
        
      3. 子组件内部通过this.$emit('方法名', 要传递的数据)方式,来调用父组件中的方法,同时把数据传递给父组件使用
        ```
      
      ## 评论列表案例
      目标:主要练习父子组件之间传值
      
      ## 使用 `this.$refs` 来获取元素和组件
      

      这是一个大大的H1

        <hr>
        <!-- 使用 ref 获取子组件 -->
        <my-com ref="mycom"></my-com>
      </div>
      
      
      ## 什么是路由
      1. 对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源;
      
      2. 对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;
      
      3. 在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由);
      
      ## 在 vue 中使用 vue-router
      1. 导入 vue-router 组件类库:
      ```html
      <!-- 1. 导入 vue-router 组件类库 -->
        <script src="./lib/vue-router-2.7.0.js"></script>
      
      1. 使用 router-link 组件来导航

        <!-- 2. 使用 router-link 组件来导航 -->
        <router-link to="/login">登录</router-link>
        <router-link to="/register">注册</router-link>
        
      2. 使用 router-view 组件来显示匹配到的组件

        <!-- 3. 使用 router-view 组件来显示匹配到的组件 -->
        <router-view></router-view>
        
      3. 创建使用Vue.extend创建组件
        ```js
        // 4.1 使用 Vue.extend 来创建登录组件
        var login = Vue.extend({
        template: ‘

        登录组件


        });

        // 4.2 使用 Vue.extend 来创建注册组件
        var register = Vue.extend({
        template: ‘

        注册组件


        });

      5. 创建一个路由 router 实例,通过 routers 属性来定义路由匹配规则
      ```js
      // 5. 创建一个路由 router 实例,通过 routers 属性来定义路由匹配规则
          var router = new VueRouter({
              //这样这里不是routers而是routes
            routes: [
              { path: '/login', component: login },
              { path: '/register', component: register }
            ]
          });
      
      1. 使用 router 属性来使用路由规则
        // 6. 创建 Vue 实例,得到 ViewModel
         var vm = new Vue({
           el: '#app',
           router: router // 使用 router 属性来使用路由规则
         });
        

      设置路由高亮

      设置路由切换动效

      在路由规则中定义参数

      比如访问路径:http://localhost:8080/register/123123123123

      1. 在规则中定义参数:
        { path: '/register/:id', component: register }
        
      2. 通过 this.$route.params来获取路由中的参数:
        var register = Vue.extend({
           template: '<h1>注册组件 --- {{this.$route.params.id}}</h1>'
         });
        

      使用 children 属性实现路由嵌套

        <div id="app">
          <router-link to="/account">Account</router-link>
      
          <router-view></router-view>
        </div>
      
        <script>
          // 父路由中的组件
          const account = Vue.extend({
            template: `<div>
              这是account组件
              <router-link to="/account/login">login</router-link> | 
              <router-link to="/account/register">register</router-link>
              <router-view></router-view>
            </div>`
          });
      
          // 子路由中的 login 组件
          const login = Vue.extend({
            template: '<div>登录组件</div>'
          });
      
          // 子路由中的 register 组件
          const register = Vue.extend({
            template: '<div>注册组件</div>'
          });
      
          // 路由实例
          var router = new VueRouter({
            routes: [
              { path: '/', redirect: '/account/login' }, // 使用 redirect 实现路由重定向
              {
                path: '/account',
                component: account,
                //注意这里是children不是childrens
                children: [ // 通过 children 数组属性,来实现路由的嵌套
                  { path: 'login', component: login }, // 注意,子路由的开头位置,不要加 / 路径符
                  { path: 'register', component: register }
                ]
              }
            ]
          });
      
          // 创建 Vue 实例,得到 ViewModel
          var vm = new Vue({
            el: '#app',
            data: {},
            methods: {},
            components: {
              account
            },
            router: router
          });
        </script>
      

      命名视图实现经典布局

      1. 标签代码结构:
        <div id="app">
         <router-view></router-view>
         <div class="content">
           <router-view name="a"></router-view>
           <router-view name="b"></router-view>
         </div>
          </div>
        
      2. JS代码:
        ```

        3. CSS 样式:
        
        
        ## `watch`属性的使用
        考虑一个问题:想要实现 `名` 和 `姓` 两个文本框的内容改变,则全名的文本框中的值也跟着改变;(用以前的知识如何实现???)
        
        1. 监听`data`中属性的改变:
        
        + =
        2. 监听路由对象的改变:
        
        登录注册
        <router-view></router-view>
        
        
        ## `computed`计算属性的使用
        1. 默认只有`getter`的计算属性:
        
        + =
        2. 定义有`getter`和`setter`的计算属性:
        
        <span>{{fullName}}</span>
        
        
        ## `watch`、`computed`和`methods`之间的对比
        1. `computed`属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
        2. `methods`方法表示一个具体的操作,主要书写业务逻辑;
        3. `watch`一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是`computed`和`methods`的结合体;
        
        ## `nrm`的安装使用
        作用:提供了一些最常用的NPM包镜像地址,能够让我们快速的切换安装包时候的服务器地址;
        什么是镜像:原来包刚一开始是只存在于国外的NPM服务器,但是由于网络原因,经常访问不到,这时候,我们可以在国内,创建一个和官网完全一样的NPM服务器,只不过,数据都是从人家那里拿过来的,除此之外,使用方式完全一样;
        
        1. 运行`npm i nrm -g`全局安装`nrm`包;
        2. 使用`nrm ls`查看当前所有可用的镜像源地址以及当前所使用的镜像源地址;
        3. 使用`nrm use npm`或`nrm use taobao`切换不同的镜像源地址;
        
        ## 相关文件
        1. [URL中的hash(井号)](http://www.cnblogs.com/joyho/articles/4430148.html)
        
        
        
        # Vue.js -04
        
        ## 在网页中会引用哪些常见的静态资源?
        + JS
         - .js  .jsx  .coffee  .ts(TypeScript  类 C# 语言)
        + CSS
         - .css  .less   .sass  .scss
        + Images
         - .jpg   .png   .gif   .bmp   .svg
        + 字体文件(Fonts)
         - .svg   .ttf   .eot   .woff   .woff2
        + 模板文件
         - .ejs   .jade  .vue【这是在webpack中定义组件的方式,推荐这么用】
        
        
        ## 网页中引入的静态资源多了以后有什么问题???
        1. 网页加载速度慢, 因为 我们要发起很多的二次请求;
        2. 要处理错综复杂的依赖关系
        
        
        ## 如何解决上述两个问题
        1. 合并、压缩、精灵图、图片的Base64编码
        2. 可以使用之前学过的requireJS、也可以使用webpack可以解决各个包之间的复杂依赖关系;
        
        ## 什么是webpack?
        webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;
        
        
        ## 如何完美实现上述的2种解决方案
        1. 使用Gulp, 是基于 task 任务的;
        2. 使用Webpack, 是基于整个项目进行构建的;
        + 借助于webpack这个前端自动化构建工具,可以完美实现资源的合并、打包、压缩、混淆等诸多功能。
        + 根据官网的图片介绍webpack打包的过程
        + [webpack官网](http://webpack.github.io/)
        
        ## webpack安装的两种方式
        1. 运行`npm i webpack@3.6.0 -g`全局安装webpack,这样就能在全局使用webpack的命令
        2. 在项目根目录中运行`npm i webpack --save -dev`安装到项目依赖中
        
        ## 初步使用webpack打包构建列表隔行变色案例
        1. 运行`npm init -y`初始化项目,使用npm管理项目中的依赖包
        2. 创建项目基本的目录结构
        3. 使用`cnpm i jquery --save`安装jquery类库
        4. 创建`main.js`并书写各行变色的代码逻辑:
        
        // 导入jquery类库
        import $ from 'jquery'
        
        // 设置偶数行背景色,索引从0开始,0是偶数
        $('#list li:even').css('backgroundColor','lightblue');
        // 设置奇数行背景色
        $('#list li:odd').css('backgroundColor','pink');
        
        5. 直接在页面上引用`main.js`会报错,因为浏览器不认识`import`这种高级的JS语法,需要使用webpack进行处理,webpack默认会把这种高级的语法转换为低级的浏览器能识别的语法;
        6. 运行`webpack 入口文件路径 输出文件路径`对`main.js`进行处理:
        
        **注意**:webpack4.x需要加上`-o`参数才行,不然会报错!!
        

        webpack src/js/main.js -o dist/bundle.js

        
        ## 使用webpack的配置文件简化打包时候的命令
        
        1. 在项目根目录中创建`webpack.config.js`
        2. 由于运行webpack命令的时候,webpack需要指定入口文件和输出文件的路径,所以,我们需要在`webpack.config.js`中配置这两个路径:
        
        // 导入处理路径的模块
        var path = require('path');
        
        // 导出一个配置对象,将来webpack在启动的时候,会默认来查找webpack.config.js,并读取这个文件中导出的配置对象,来进行打包处理
        module.exports = {
            entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件
            output: { // 配置输出选项
                path: path.resolve(__dirname, 'dist'), // 配置输出的路径
                filename: 'bundle.js' // 配置输出的文件名
            }
        }
        
        
        ## 实现webpack的实时打包构建
        1. 由于每次重新修改代码之后,都需要手动运行webpack打包的命令,比较麻烦,所以使用`webpack-dev-server`来实现代码实时打包编译,当修改代码之后,会自动进行打包构建。
        2. 先在项目本地安装`npm i webpack@3.0.0`,然后`cnpm i webpack-dev-server@2.9.3 --save -dev`安装到开发依赖
        3. 安装完成之后,在命令行直接运行`webpack-dev-server`来进行打包,发现报错,此时需要借助于`package.json`文件中的指令,来进行运行`webpack-dev-server`命令,在`package.json文件的scripts`节点下新增`"dev": "webpack-dev-server"`指令,发现可以进行实时打包,但是dist目录下并没有生成`bundle.js`文件,这是因为`webpack-dev-server`将打包好的文件放在了内存中
         + 把`bundle.js`放在内存中的好处是:由于需要实时打包编译,所以放在内存中速度会非常快
         + 这个时候访问webpack-dev-server启动的`http://localhost:8080/`网站,发现是一个文件夹的面板,需要点击到src目录下,才能打开我们的index首页,此时引用不到bundle.js文件,需要修改index.html中script的src属性为:`<script src="../bundle.js"></script>`
         + 为了能在访问`http://localhost:8080/`的时候直接访问到index首页,可以使用`--contentBase src`指令来修改dev指令,指定启动的根目录:
        

        “dev”: “webpack-dev-server –contentBase src”

        同时修改index页面中script的src属性为`<script src="bundle.js"></script>`
        
        **注意**:webpack4.x版本要安装这个:`npm i webpack-cli` 否则会报错
        
        * 启动项目:经过上一步的配置,在终端输入下面命令即可启动项目访问默认页面。
        

        npm run dev

        
        ## 使用`html-webpack-plugin`插件配置启动页面
        由于使用`--contentBase`指令的过程比较繁琐,需要指定启动的目录,同时还需要修改index.html中script标签的src属性,所以推荐大家使用`html-webpack-plugin`插件配置启动页面.
        1. 运行`cnpm i html-webpack-plugin@3 --save-dev`安装到开发依赖
        2. 修改`webpack.config.js`配置文件如下:
        
        // 导入处理路径的模块
        var path = require('path');
        // 导入自动生成HTMl文件的插件
        var htmlWebpackPlugin = require('html-webpack-plugin');
        
        module.exports = {
            entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件
            output: { // 配置输出选项
                path: path.resolve(__dirname, 'dist'), // 配置输出的路径
                filename: 'bundle.js' // 配置输出的文件名
            },
            plugins:[ // 添加plugins节点配置插件
                new htmlWebpackPlugin({
                    template:path.resolve(__dirname, 'src/index.html'),//模板路径
                    filename:'index.html'//自动生成的HTML文件的名称
                })
            ]
        }
        
        3. 修改`package.json`中`script`节点中的dev指令如下:
        

        “dev”: “webpack-dev-server”

        4. 将index.html中script标签注释掉,因为`html-webpack-plugin`插件会自动把bundle.js注入到index.html页面中!
        
        ## 实现自动打开浏览器、热更新和配置浏览器的默认端口号
        **注意:热更新在JS中表现的不明显,可以从一会儿要讲到的CSS身上进行介绍说明!**
        
        ### 方式1:
        + 修改`package.json`的script节点如下,其中`--open`表示自动打开浏览器,`--port 4321`表示打开的端口号为4321,`--hot`表示启用浏览器热更新:
        

        “dev”: “webpack-dev-server –hot –port 4321 –open”

        
        ### 方式2:
        
        0. 修改`package.json`的script节点
        

        “dev”: “webpack-dev-server”

        
        1. 修改`webpack.config.js`文件,新增`devServer`节点如下:
        

        devServer:{
        hot:true,
        open:true,
        port:4321
        }

        2. 在头部引入`webpack`模块:
        

        var webpack = require(‘webpack’);

        3. 在新增`plugins`节点,并在节点下新增:
        

        new webpack.HotModuleReplacementPlugin()

        
        ## 使用webpack打包css文件
        
        0. ==在main.js中导入css文件==
        

        import ‘./css/index.css’

        
        1. 默认只能导入js文件,所以需要安装`loader`,运行`cnpm i style-loader@2 css-loader@3 --save-dev`
        2. 修改`webpack.config.js`这个配置文件:
        

        module: { // 用来配置第三方loader模块的
        rules: [ // 文件的匹配规则
        { test: /.css$/, use: [‘style-loader’, ‘css-loader’] }//处理css文件的规则
        ]
        }

        3. 注意:`use`表示使用哪些模块来处理`test`所匹配到的文件;`use`中相关loader模块的调用顺序是从后向前调用的;
        
        ## 使用webpack打包less文件
        1. 运行`cnpm i less-loader@3 less@2 -D`
        2. 修改`webpack.config.js`这个配置文件:
        

        { test: /.less$/, use: [‘style-loader’, ‘css-loader’, ‘less-loader’] },

        
        ## 使用webpack打包sass文件
        1. 运行`cnpm i sass-loader@6 node-sass@4 --save-dev`
        2. 在`webpack.config.js`中添加处理sass文件的loader模块:
        

        { test: /.scss$/, use: [‘style-loader’, ‘css-loader’, ‘sass-loader’] }

        
        ## 使用webpack处理css中的路径
        1. 运行`cnpm i url-loader@0 file-loader@1 --save-dev`
        2. 在`webpack.config.js`中添加处理url路径的loader模块:
        

        { test: /.(png|jpg|gif)$/, use: ‘url-loader’ }

        3. 可以通过`limit`指定进行base64编码的图片大小;只有小于指定字节(byte)的图片才会进行base64编码:
        

        { test: /.(png|jpg|gif)$/, use: ‘url-loader?limit=43960’ },

        
        **注意**:也可以来处理字体文件。
        
        ## 使用babel处理高级JS语法
        
        1. 运行`cnpm i babel-core babel-loader@7 babel-plugin-transform-runtime --save-dev`安装babel的相关loader包
        
           **注意**:这里babel-loader@7 否则会下载8版本
        
           https://blog.csdn.net/weixin_33727510/article/details/93264765
        
        2. 运行`cnpm i babel-preset-env babel-preset-stage-0 --save-dev`安装babel转换的语法
        
        3. 在`webpack.config.js`中添加相关loader模块,其中需要注意的是,一定要把`node_modules`文件夹添加到排除项:
        

        { test: /.js$/, use: ‘babel-loader’, exclude: /node_modules/ }

        4. 在项目根目录中添加`.babelrc`文件,并修改这个配置文件如下:
        

        {
        “presets”:[“env”, “stage-0”],
        “plugins”:[“transform-runtime”]
        }

        5. **注意:语法插件`babel-preset-es2015`可以更新为`babel-preset-env`,它包含了所有的ES相关的语法;**
        
        ## 相关文章
        [babel-preset-env:你需要的唯一Babel插件](https://segmentfault.com/p/1210000008466178)
        [Runtime transform 运行时编译es6](https://segmentfault.com/a/1190000009065987)
        
        # Vue.js-05
        
        ## 注意:
        
        有时候使用`npm i node-sass -D`装不上,这时候,就必须使用 `cnpm i node-sass -D`
        
        ## 在普通页面中使用render函数渲染组件
        
        
        
        ## 在webpack中配置.vue组件页面的解析
        
        1. 运行`cnpm i vue -S`将vue安装为运行依赖;
        
        2. 运行`cnpm i vue-loader@14 vue-template-compiler -D`将解析转换vue的包安装为开发依赖;
        
        3. 运行`cnpm i style-loader css-loader -D`将解析转换CSS的包安装为开发依赖,因为.vue文件中会写CSS样式;
        
        4. 在`webpack.config.js`中,添加如下`module`规则:
        

        module: {

        rules: [
        
          { test: /\.css$/, use: ['style-loader', 'css-loader'] },
        
          { test: /\.vue$/, use: 'vue-loader' }
        
        ]
        

        }

        
        5. 创建`App.vue`组件页面:
        
        <template>
        
          <!-- 注意:在 .vue 的组件中,template 中必须有且只有唯一的根元素进行包裹,一般都用 div 当作唯一的根元素 -->
        
          <div>
        
            <h1>这是APP组件 - {{msg}}</h1>
        
            <h3>我是h3</h3>
        
          </div>
        
        </template>
        
        
        
        <script>
        
        // 注意:在 .vue 的组件中,通过 script 标签来定义组件的行为,需要使用 ES6 中提供的 export default 方式,导出一个vue实例对象
        
        export default {
        
          data() {
        
            return {
        
              msg: 'OK'
        
            }
        
          }
        
        }
        
        </script>
        
        
        
        <style scoped>
        
        h1 {
        
          color: red;
        
        }
        
        </style>
        
        
        6. 创建`main.js`入口文件:
        
        // 导入 Vue 组件
        
        import Vue from 'vue'
        
        
        
        // 导入 App组件
        
        import App from './components/App.vue'
        
        
        
        // 创建一个 Vue 实例,使用 render 函数,渲染指定的组件
        
        var vm = new Vue({
        
          el: '#app',
        
          render: c => c(App)
        
        });
        
        
        ## 在使用webpack构建的Vue项目中使用模板对象?
        1. 在`webpack.config.js`中添加`resolve`属性:
        

        resolve: {
        alias: {
        ‘vue$’: ‘vue/dist/vue.esm.js’
        }
        }

        
        
        
        ## ES6中语法使用总结
        
        1. 使用 `export default` 和 `export` 导出模块中的成员; 对应ES5中的 `module.exports` 和 `export`
        
        2. 使用 `import ** from **` 和 `import '路径'` 还有 `import {a, b} from '模块标识'` 导入其他模块
        
        3. 使用箭头函数:`(a, b)=> { return a-b; }`
        
        
        
        ## 在vue组件页面中,集成vue-router路由模块
        
        [vue-router官网](https://router.vuejs.org/)
        
        1. 导入路由模块:
        

        import VueRouter from ‘vue-router’

        
        2. 安装路由模块:
        

        Vue.use(VueRouter);

        
        3. 导入需要展示的组件:
        

        import login from ‘./components/account/login.vue’

        import register from ‘./components/account/register.vue’

        
        4. 创建路由对象:
        

        var router = new VueRouter({

        routes: [

        { path: '/', redirect: '/login' },
        
        { path: '/login', component: login },
        
        { path: '/register', component: register }
        

        ]

        });

        
        5. 将路由对象,挂载到 Vue 实例上:
        

        var vm = new Vue({

        el: ‘#app’,

        // render: c => { return c(App) }

        render(c) {

        return c(App);
        

        },

        router // 将路由对象,挂载到 Vue 实例上

        });

        
        6. 改造App.vue组件,在 template 中,添加`router-link`和`router-view`:
        
        <router-link to="/login">登录</router-link>
        
        <router-link to="/register">注册</router-link>
        
        
        
        <router-view></router-view>
        
        
        
        
        ## 组件中的css作用域问题
        
        
        
        ## 抽离路由为单独的模块
        
        
        
        ## 使用 饿了么的 MintUI 组件
        
        [Github 仓储地址](https://github.com/ElemeFE/mint-ui)
        
        [Mint-UI官方文档](http://mint-ui.github.io/#!/zh-cn)
        
        1. 导入所有MintUI组件:
        

        import MintUI from ‘mint-ui’

        
        2. 导入样式表:
        

        import ‘mint-ui/lib/style.css’

        
        3. 在 vue 中使用 MintUI:
        

        Vue.use(MintUI)

        
        4. 使用的例子:
        

        primary

        
        
        
        ## 使用 MUI 组件
        
        [官网首页](http://dev.dcloud.net.cn/mui/)
        
        [文档地址](http://dev.dcloud.net.cn/mui/ui/)
        
        1. 导入 MUI 的样式表:
        

        import ‘../lib/mui/css/mui.min.css’

        
        2. 在`webpack.config.js`中添加新的loader规则:
        

        { test: /.(png|jpg|gif|ttf)$/, use: ‘url-loader’ }

        
        3. 根据官方提供的文档和example,尝试使用相关的组件
        
        
        
        ## 将项目源码托管到oschina中
        
        1. 点击头像 -> 修改资料 -> SSH公钥 [如何生成SSH公钥](http://git.mydoc.io/?t=154712)
        
        2. 创建自己的空仓储,使用 `git config --global user.name "用户名"` 和 `git config --global user.email ***@**.com` 来全局配置提交时用户的名称和邮箱
        
        3. 使用 `git init` 在本地初始化项目
        
        4. 使用 `touch README.md` 和 `touch .gitignore` 来创建项目的说明文件和忽略文件;
        
        5. 使用 `git add .` 将所有文件托管到 git 中
        
        6. 使用 `git commit -m "init project"` 将项目进行本地提交
        
        7. 使用 `git remote add origin 仓储地址`将本地项目和远程仓储连接,并使用origin最为远程仓储的别名
        
        8. 使用 `git push -u origin master` 将本地代码push到仓储中
        
        
        
        ## App.vue 组件的基本设置
        
        1. 头部的固定导航栏使用 `Mint-UI` 的 `Header` 组件;
        
        2. 底部的页签使用 `mui` 的 `tabbar`;
        
        3. 购物车的图标,使用 `icons-extra` 中的 `mui-icon-extra mui-icon-extra-cart`,同时,应该把其依赖的字体图标文件 `mui-icons-extra.ttf`,复制到 `fonts` 目录下!
        
        4. 将底部的页签,改造成 `router-link` 来实现单页面的切换;
        
        5. Tab Bar 路由激活时候设置高亮的两种方式:
        
         + 全局设置样式如下:
        
         .router-link-active{
        
              color:#007aff !important;
        
        }
        
        
        + 或者在 `new VueRouter` 的时候,通过 `linkActiveClass` 来指定高亮的类:
        
         // 创建路由对象
        
        var router = new VueRouter({
        
          routes: [
        
            { path: '/', redirect: '/home' }
        
          ],
        
          linkActiveClass: 'mui-active'
        
        });
        
        
        
        
        ## 实现 tabbar 页签不同组件页面的切换
        
        1. 将 tabbar 改造成 `router-link` 形式,并指定每个连接的 `to` 属性;
        
        2. 在入口文件中导入需要展示的组件,并创建路由对象:
        
        // 导入需要展示的组件
        
        import Home from './components/home/home.vue'
        
        import Member from './components/member/member.vue'
        
        import Shopcar from './components/shopcar/shopcar.vue'
        
        import Search from './components/search/search.vue'
        
        
        
        // 创建路由对象
        
        var router = new VueRouter({
        
          routes: [
        
            { path: '/', redirect: '/home' },
        
            { path: '/home', component: Home },
        
            { path: '/member', component: Member },
        
            { path: '/shopcar', component: Shopcar },
        
            { path: '/search', component: Search }
        
          ],
        
          linkActiveClass: 'mui-active'
        
        });
        
        
        
        
        ## 使用 mt-swipe 轮播图组件
        
        1. 假数据:
        

        lunbo: [

            'http://www.itcast.cn/images/slidead/BEIJING/2017440109442800.jpg',
        
            'http://www.itcast.cn/images/slidead/BEIJING/2017511009514700.jpg',
        
            'http://www.itcast.cn/images/slidead/BEIJING/2017421414422600.jpg'
        
          ]
        
        
        2. 引入轮播图组件:
        
        <div class="home-swipe">
        
          <mt-swipe :auto="4000">
        
            <mt-swipe-item v-for="(item, i) in lunbo" :key="i">
        
              <img :src="item" alt="">
        
            </mt-swipe-item>
        
          </mt-swipe>
        
        </div>
        
      
      
      
      ## 在`.vue`组件中使用`vue-resource`获取数据
      
      1. 运行`cnpm i vue-resource -S`安装模块
      
      2. 导入 vue-resource 组件
      

      import VueResource from ‘vue-resource’

      
      3. 在vue中使用 vue-resource 组件
      

      Vue.use(VueResource);

      
      
      
      
------ 本文结束,感谢您的阅读 ------
本文作者: 程序员青阳
版权声明: 本文采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。