小白都能看能的Vue,轻松上手,搭建大型项目轻轻松松

Vue.js笔记
1.指令:
v-cloak: 主要功能是解决Vue存在的插值表达式 闪动问题
v-text: 用于将数据填充到标签中,和插值表达式作用相同
v-html: 用法和 v-text 相似,但是也可以将html片段填充到标签中
v-once: 只加载一次,后续数据改变,插值内容数据将不再改变
v-model: 双向数据绑定,当数据改变时,数据具有双向改变的特性
v-pre: 跳过编译过程,原样输出
实例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>指令</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>

</head>

<body>

    <!--   {{}}  插值表达式 就是将数据插入到标签中
        1、v-cloak 解决插值表达式闪动问题。配合style使用
        2、v-text 用于将数据填充到标签中 和插值表达式作用相同,但是没有闪动的问题
        3. v-html 用法和v-text 相似。但是他可以将html片段填充到标签中,有安全问题,一般只在可信用的网站使用
        4. v-pre 跳过编译过程,原样输出
        5. v-once 只加载一次 后续数据改变,插值内容数据将不再改变
        6. v-model 双向数据绑定,当数据改变的时候,视图跟随改变,当视图改变的时候,数据也跟随改变
     -->
    <div id="app" v-cloak> {{ msg }}
        <p v-text='text'></p>

        <p v-html="html"></p>

        <p v-pre>{{}}</p>

        <p v-once>{{msg1}}</p>
        <div>
            <p>{{msg3}}</p>
            <input type="text" v-model="msg3">
        </div>

    </div>
    <script src="/vue.js"></script>
    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                msg: "hello world",
                text: "<h1> 大大大大 </h1>",
                html: "<i> 小小 小 </i>",
                msg1: "hello Vue",
                msg3: "双向数据绑定"
            },
        })
    </script>
</body>

</html>

MVVM开发思想
model 数据
views 视图
views-model
事件绑定:
(不带括号)v-on:click=“函数名” ==== > 简写模式 @click=“函数名”
(带括号传参)v-on:click=“函数名()” ==== > 简写模式 @click=“函数名()”

实例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>事件绑定</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app">
        <div v-cloak>{{num}} </div>
        <div>
            <input type="button" value="按钮" v-on:click="num++">
            <!--//行内式一般写法  不推荐行内式-->

            <input type="button" value="按钮1" @click="num++">
            <!--//行内式简易写法 -->

            <input type="button" value="按钮2" @click="handle">
            <!-- 推荐写法,调用函数 不带括号-->

            <input type="button" value="按钮3" @click="handle()">
            <!-- 推荐写法,调用函数 带括号便于传参 -->

        </div>

    </div>
    <script src="vue.js"></script>
    <script>
        var vm = new Vue({
            el: '#app',
            data: {
                num: 0
            },
            methods: {
                handle: function() {
                    this.num++;
                }
            }
        })
    </script>
</body>

</html>

事件参数及按键修饰符
@keyup.enter:键盘确认修饰符
@keyup.delete:键盘删除修饰符
Vue.config.keyCodes.f1 = f2 其中f1 名字是自定义的 但是f2 的值必须是按键对应的 eventkeyCode 的值

实例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>事件绑定</title>
    <style>
        [v-cloak] {
            display: none;
        }
    </style>
</head>

<body>
    <div id="app">
        <div v-cloak>{{num}} </div>
        <div @click="handle3()">
            <!--此时如果不对 a 进行阻止冒泡行为 将会冒泡到handle3上 在冒泡的事件上添加stop即可-->
            <input type="button" value="按钮" @click="handle">
            <!-- 推荐写法,调用函数 不带括号-->

            <input type="button" value="按钮1" @click="handle1(123,$event)">
            <!-- 推荐写法,调用函数 带括号便于传参 -->
            <!-- 传参必须时事件对象必须是 $event  固定写法,而且必须写在传参的最后面 -->

            <a href="http://www.baidu.com" @click.stop.prevent="handle2()">百度</a>
            <!-- 此时如果不对 a 链接进行默认行为阻止就会链接到百度,我们使用 present 阻止默认事件行为  -->
        </div>
        <hr>
        <hr>
        <div>
            <input type="text" name="username" placeholder="用户名" v-model="uname" @keyup.delete="dele"> <br>
            <!-- @keyup.delete 进行键盘delete快速删除-->
            <br>
            <input type="password" name="pwd" placeholder="密码" @keyup.enter="getSubmit" v-model="psd"> <br>
            <!-- 使用v-on:keyup.enter 进行键盘确认-->
            <input type="submit" value="提交" @click="getSubmit">
        </div>
    </div>
    <script src="vue.js"></script>
    <script>
        // 自定义按键修饰符
        Vue.congif.keyCodes.f1 = f2 // 其中 f1 名字是自定义的,但是f2 的值必须是按键对应的 eventkeyCode值
        var vm = new Vue({
            el: '#app',
            data: {
                num: 0,
                uname: "",
                psd: ""
            },
            methods: {
                handle: function() {
                    this.num++;
                },
                handle1: function(p, event) {
                    console.log(p);
                    console.log(event)
                    this.num++;
                },
                handle2: function() {
                    alert(1);
                },
                handle3: function() {
                    alert(3);
                },
                getSubmit: function() {
                    console.log(this.uname, this.psd)
                },
                dele: function() {
                    this.uname = "";
                }
            }
        })
    </script>
</body>

</html>

简单计算机案例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>计算机案例</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="text" placeholder="A值" v-model="aData"> <br>
        <input type="text" placeholder="B值" v-model="bData"> <br>
        <button @click="handle">计算</button> <br>
        <div>结果 <span>:{{result}}</span></div>
    </div>

    <script>
        let vm = new Vue({
            el: "#app",
            data: {
                result: "",
                aData: "",
                bData: ""
            },
            methods: {
                handle: function() {
                    this.result = parseInt(this.aData) + parseInt(this.bData);
                }
            }
        })
    </script>
</body>

</html>

属性绑定 v-bind:
v-bind:进行属性的绑定 === >简化写法 直接使用 : 代替
实例如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>动态处理属性</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">

        <a v-bind:href="url">百度</a>
        <!-- v-bind:动态获取-->
        <!-- v-bind 是 实现 v-model 的底层原理对象 -->
        <input type="text">

        <a :href="url">百度1</a>
    </div>

    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                url: "http://www.baidu.com"
            },
            methods: {
                handle: function() {

                }
            }
        })
    </script>
</body>

</html>

样式绑定 操作 class 和 style

  • class 样式:
    使用对象的方式进行类样式的设置
    v-bind:class="{active:isActive,bgc:isBgc}" 其中active 为定义的类名 isActive是布尔标志 true 或者 false
    使用数组的方式进行类样式设置
    v-bind:class="[activeArray,bgcArray]" 其中activeArray 为定义的类样式名的变量名
    使用对象和数组的方式混合设置类样式
    v-bind:class="[activeArray,bgcArray,{fize:isFize}]" 用法和上述单个用法相同,只是将他们混合一起使用了。
    如果在行内式 放置很多类样式,后期维护很不方便,此时我们可以使用简便的方式,将类样式定义在Vue实例对象data中,详情见代码

实例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>样式操作</title>
    <script src="vue.js"></script>
    <style>
        .active {
            border: 1px solid red;
            width: 100px;
            height: 100px;
        }
        
        .bgc {
            background-color: #000;
        }
        
        .fize {
            font-size: 30px;
            color: aliceblue;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- 使用class类进行操作 -->
        <!-- <div v-bind:class="{active:isActive,bgc:isBgc}"></div> -->
        <!--{} 使用的对象的方式进行类样式的设置 -->
        <!-- <button @click="handle">对象改变</button> -->

        <!-- <div v-bind:class="[activeArray,bgcArray]"></div> -->
        <!-- {} 使用的对象的方式进行类样式的设置 -->
        <!-- <button @click="handle">数组改变</button> -->

        <!-- 对象操作和数组操作混合使用 -->
        <div v-bind:class="[activeArray,bgcArray,{fize:isFize}]">测试</div>
        <!-- {} 使用的对象的方式进行类样式的设置 -->
        <button @click="handle">数组改变</button>


        <!-- <div v-bind:class="objData">gogo</div> -->
        <!--{} 使用的对象的方式进行类样式的设置 -->
        <!-- <button @click="handle">对象改变</button> -->

        <!-- <div v-bind:class="arrData">gogo</div> -->
        <!-- {} 使用的对象的方式进行类样式的设置 -->
        <!-- <button @click="handle">数组改变</button> -->


    </div>

    <script>
        let vm = new Vue({
            el: '#app',
            data: {
                // isActive: true,
                // isBgc: true,
                activeArray: "active",
                bgcArray: "bgc",
                isFize: true,
                // 对象类 简写
                // objData: {
                //     active: true,
                //     bgc: true
                // }
                // // 数组类 简写
                // arrData: ["active", "bgc"]
            },
            methods: {
                handle: function() {
                    // this.isActive = !this.isActive;
                    // this.isBgc = !this.isBgc
                    // this.bgcArray = "";
                    // 对象类 简写
                    // this.objData.bgc = false
                }
            }
        })
    </script>
</body>

</html>
  • style 操作样式
    直接在style后进行对象设置样式 在Vue实例data中设置数据
    也可以使用直接参数对象的方式
    也可以使用数组的方式传输,但是相同的样式会被后面的覆盖
    实例代码:
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>样式操作 style</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <div :style="{color:colorStyle}">测试1</div>
        <div :style="objStyle">测试2</div>
        <div :style="[objStyle,errStyle]">测试2</div>

    </div>
    <script>
        let vm = new Vue({
            el: "#app",
            data: {
                colorStyle: "blue",
                objStyle: {
                    color: "red",
                },
                errStyle: {
                    color: "skyblue",
                    fontSize: "30px"
                }
            },
            methods: {

            }
        })
    </script>
</body>

</html>

分支结构 v-if v-else-if v-else:
使用v-if v-else-if v-else 直接在行内式进行判断
实例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>分支循环结构</title>
    <script src="vue.js"></script>
</head>

<body>

    <div id="app">
        <!-- 分支结构 -->
        <div v-if="sorce>90">优秀</div>
        <div v-else-if="score<90&&score>=80">合格</div>
        <div v-else="sorce>50&&soecr<60">极差</div>
        <div v-show="flag">test</div>
        <!--已经加载 并且会显示在结构中-->
        <button @click="handle"> 点击</button>
    </div>
    <script>
        let vm = new Vue({
            el: "#app",
            data: {
                sorce: 98,
                flag: false
            },
            methods: {
                handle: function() {
                    this.flag = !this.flag;
                }
            }
        });
    </script>
</body>

</html>

循环结构 遍历数组
使用 v-for =“item in 数组名” item为遍历的数组的每一项
使用 v-for ="(item,index) in 数组名" item为遍历的数组的每一项,index为数组的索引
:key=“item.id” 主要是为了优化Vue

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>循环结构遍历数组 和对象</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <div>水果列表</div>
        <ul>
            <li v-for="item in fruits">{{item}}</li>
            <li v-for="(item,index) in fruits">{{item+"-----"+index}}</li>

            <li :key="item.id" v-for="(item,index) in myFruits">
                <span>{{item.ename}}</span>
                <span>------</span>
                <span>{{item.cname}}</span>
            </li>

        </ul>

    </div>
    <script>
        let vm = new Vue({
            el: "#app",
            data: {
                fruits: ['apple', 'banana', 'orange'],
                myFruits: [{
                    id: 1,
                    ename: "apple",
                    cname: "苹果"
                }, {
                    id: 2,
                    ename: "banan",
                    cname: "香蕉"
                }, {
                    id: 3,
                    ename: "orange",
                    cname: "橛子"
                }]
            },
            methods: {

            }
        })
    </script>
</body>

</html>

遍历对象:
v-for ="(value,key,index) in obj" 其中 value 是值 key 是对象的变量 index是索引
实例代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  
</head>
<body>
  <div id="app">
    <div v-if='v==13' v-for='(v,k,i) in obj'>{{v + '---' + k + '---' + i}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    // 使用原生js遍历对象
    var obj = {
      uname: 'lisi',
      age: 12,
      gender: 'male'
    }
    for(var key in obj) {
      console.log(key, obj[key])
    }
    /*
      循环结构
    */
    var vm = new Vue({
      el: '#app',
      data: {
        obj: {
          uname: 'zhangsan',
          age: 13,
          gender: 'female'
        }
      }
    });
  </script>
</body>
</html>

表单基本操作
为表单设置 v-model 值在 Vue实例data中设置,其中type=text 直接设置v-model 即可
type=radio的 v-model 的值设置相同 设置value值 对应男和女
type=checkbox的 v-model 的值设置相同 设置value值 对应每个爱好
select的 v-model 直接设置值 设置value值 如果想选中多个选项使用multiple属性
对于 textatea 直接设置v-model 即可

案例如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <style type="text/css">
  
  form div {
    height: 40px;
    line-height: 40px;
  }
  form div:nth-child(4) {
    height: auto;
  }
  form div span:first-child {
    display: inline-block;
    width: 100px;
  }
  </style>
</head>
<body>
  <div id="app">
    <form action="http://itcast.cn">
      <div>
        <span>姓名:</span>
        <span>
          <input type="text" v-model='uname'>
        </span>
      </div>
      <div>
        <span>性别:</span>
        <span>
          <input type="radio" id="male" value="1" v-model='gender'>
          <label for="male">男</label>
          <input type="radio" id="female" value="2" v-model='gender'>
          <label for="female">女</label>
        </span>
      </div>
      <div>
        <span>爱好:</span>
        <input type="checkbox" id="ball" value="1" v-model='hobby'>
        <label for="ball">篮球</label>
        <input type="checkbox" id="sing" value="2" v-model='hobby'>
        <label for="sing">唱歌</label>
        <input type="checkbox" id="code" value="3" v-model='hobby'>
        <label for="code">写代码</label>
      </div>
      <div>
        <span>职业:</span>
        <select v-model='occupation' multiple>
          <option value="0">请选择职业...</option>
          <option value="1">教师</option>
          <option value="2">软件工程师</option>
          <option value="3">律师</option>
        </select>
      </div>
      <div>
        <span>个人简介:</span>
        <textarea v-model='desc'></textarea>
      </div>
      <div>
        <input type="submit" value="提交" @click.prevent='handle'>
      </div>
    </form>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      表单基本操作
    */
    var vm = new Vue({
      el: '#app',
      data: {
        uname: 'lisi',
        gender: 2,
        hobby: ['2','3'],
        // occupation: 3
        occupation: ['2','3'],
        desc: 'nihao'
      },
      methods: {
        handle: function(){
          // console.log(this.uname)
          // console.log(this.gender)
          // console.log(this.hobby.toString())
          // console.log(this.occupation)
          console.log(this.desc)

        }
      }
    });
  </script>
</body>
</html>

表单域修饰符
number:转化为数值
trim:去掉开始和结尾处的空格
lazy:将input事件切换为change事件
用法:v-model.number=“age”
实例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" v-model.number='age'>
    <input type="text" v-model.trim='info'>
    <input type="text" v-model.lazy='msg'>
    <div>{{msg}}</div>
    <button @click='handle'>点击</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      表单域修饰符
    */
    var vm = new Vue({
      el: '#app',
      data: {
        age: '',
        info: '',
        msg: ''
      },
      methods: {
        handle: function(){
          // console.log(this.age + 13)
          // console.log(this.info.length)
        }
      }
    });
  </script>
</body>
</html>

自定义指令用法
为何需要自定义指令:因为内置指令不能满足我们的开发要求
使用 directive 进行定义
带参数的自定义指令 使用binding 进行设置参数 定义的是全局的指令
局部指令用法 ==> 是定义的局部的指令 同样使用directives 进行定义
局部指令的内部代码结构和全局的指令一样

  Vue.directive(‘color', {
    inserted: function(el, binding) {
      el.style.backgroundColor = binding.value.color;
    }
  })

使用指令的用法

  <input type="text" v-color='{color:"orange"}'>

不带参数的自定义指令实例代码:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" v-focus>
    <input type="text">
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      自定义指令
    */
    Vue.directive('focus', {
      inserted: function(el){
        // el表示指令所绑定的元素
        el.focus();
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {
        
      },
      methods: {
        handle: function(){
          
        }
      }
    });
  </script>
</body>
</html>

带参数的自定义指令实例代码
只要使用binding 进行设置参数

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" v-color='msg'>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      自定义指令-带参数
    */
    Vue.directive('color', {
      bind: function(el, binding){
        // 根据指令的参数设置背景色
        // console.log(binding.value.color)
        el.style.backgroundColor = binding.value.color;
      }
    });
    var vm = new Vue({
      el: '#app',
      data: {
        msg: {
          color: 'blue'
        }
      },
      methods: {
        handle: function(){
          
        }
      }
    });
  </script>
</body>
</html>

局部指令用法代码实例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <input type="text" v-color='msg'>
    <input type="text" v-focus>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      自定义指令-局部指令
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: {
          color: 'red'
        }
      },
      methods: {
        handle: function(){
          
        }
      },
      **directives**: {
        color: {
          bind: function(el, binding){
            el.style.backgroundColor = binding.value.color;
          }
        },
        focus: {
          inserted: function(el) {
            el.focus();
          }
        }
      }
    });
  </script>
</body>
</html>

计算属性
为什么需要计算属性:表达式的计算逻辑可能比较复杂,使用计算属性可能使模板内容更加简洁
需要处理哪个比较复杂的业务逻辑就在computed中进行业务逻辑代码书写
计算属性和方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
实例 : 实现nihao进行翻转,如果在行内式进行计算太复杂,此时就需要使用计算属性
使用 computed 进行完成
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <div>{{reverseString}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      计算属性
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: 'Nihao'
      },
      computed: {
        reverseString: function(){
          return this.msg.split('').reverse().join('');
        }
      }
    });
  </script>
</body>
</html>

侦听器的用法和概念:
应用场景:数据变化时执行异步或开销较大的操作
监听哪个数据就在watch中对哪个数据监听
侦听器使用 watch 进行设置,主要进行数据动态监测
用途:当侦听的数据一旦发生变化就告诉侦听器所绑定的方法进行相应的业务逻辑处理
实例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <div>
            <span>名:</span>
            <span>
        <input type="text" v-model='firstName'>
      </span>
        </div>
        <div>
            <span>姓:</span>
            <span>
        <input type="text" v-model='lastName'>
      </span>
        </div>
        <div>{{fullName}}</div>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>
    <script type="text/javascript">
        /*
              侦听器
            */
        var vm = new Vue({
            el: '#app',
            data: {
                firstName: 'Jim',
                lastName: 'Green',
                // fullName: 'Jim Green'
            },
            computed: {
                fullName: function() {
                    return this.firstName + ' ' + this.lastName;
                }
            },
            watch: {
                firstName: function(val) {
                    this.fullName = val + ' ' + this.lastName;
                },
                lastName: function(val) {   // val表示变化之后的值
                    this.fullName = this.firstName + ' ' + val;
                }
            }
        });
    </script>
</body>

</html>

使用侦听器模拟用户名的重复性

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>侦听器案例</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        名字:<input type="text" v-model="uname"> <span>{{tip}}</span>
    </div>

    <script>
        let vm = new Vue({
            el: "#app",
            data: {
                uname: "",
                tip: ""
            },
            methods: {
                checkName: function(uname) {
                    var that = this;
                    setTimeout(() => {
                        if (uname === "admin") {
                            that.tip = "用户名已经存在"
                        } else {
                            that.tip = "用户名可以使用"
                        }
                    }, 2000);
                }
            },
            watch: {
                // 监听uname
                uname: function(val) {
                    // 调用后台接口模拟验证
                    this.checkName(val);
                    this.tip = "正在验证。。。"
                }
            }
        })
    </script>
</body>

</html>

过滤器
过滤器的作用:格式化数据:将字符串首字母转化为大写,将日期格式化相应的格式

首先我们可以自定义一个过滤器,通过语法:

Vue.filter(‘过滤器名称’, function(value){
     // 过滤器业务逻辑
  })

我们也可以定义局部过滤器 filters

filters: {
                lower: function(val) {
                    return val.charAt(0).toLowerCase() + val.slice(1);
                }
            }

实例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>过滤器基本</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <input type="text" v-model="msg">
        <div>{{msg | upper}}</div>
        <div>{{msg | upper | lower}}</div>
    </div>
    <script>
        // Vue.filter(‘过滤器名称’, function(value){
        //      // 过滤器业务逻辑
        // })
        // 自定义全局的 过滤器
        Vue.filter("upper", function(val) {
            return val.charAt(0).toUpperCase() + val.slice(1);
        })
        let vm = new Vue({
            el: "#app",
            data: {
                msg: ""
            },
            // 定义局部的过滤器
            filters: {
                lower: function(val) {
                    return val.charAt(0).toLowerCase() + val.slice(1);
                }
            }
        })
    </script>
</body>

</html>

另外我们还有带参数的过滤器

  Vue.filter(‘format’, function(value, arg1){
     // value就是过滤器传递过来的参数
  })

过滤器的使用

 <div>{{date | format(‘yyyy-MM-dd')}}</div>

带参数过滤器案例如下:格式化日期格式


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{date | format('yyyy-MM-dd hh:mm:ss')}}</div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      过滤器案例:格式化日期
      
    */
    // Vue.filter('format', function(value, arg) {
    //   if(arg == 'yyyy-MM-dd') {
    //     var ret = '';
    //     ret += value.getFullYear() + '-' + (value.getMonth() + 1) + '-' + value.getDate();
    //     return ret;
    //   }
    //   return value;
    // })
    Vue.filter('format', function(value, arg) {
      function dateFormat(date, format) {
          if (typeof date === "string") {
              var mts = date.match(/(\/Date\((\d+)\)\/)/);
              if (mts && mts.length >= 3) {
                  date = parseInt(mts[2]);
              }
          }
          date = new Date(date);
          if (!date || date.toUTCString() == "Invalid Date") {
              return "";
          }
          var map = {
              "M": date.getMonth() + 1, //月份 
              "d": date.getDate(), //日 
              "h": date.getHours(), //小时 
              "m": date.getMinutes(), //分 
              "s": date.getSeconds(), //秒 
              "q": Math.floor((date.getMonth() + 3) / 3), //季度 
              "S": date.getMilliseconds() //毫秒 
          };

          format = format.replace(/([yMdhmsqS])+/g, function(all, t) {
              var v = map[t];
              if (v !== undefined) {
                  if (all.length > 1) {
                      v = '0' + v;
                      v = v.substr(v.length - 2);
                  }
                  return v;
              } else if (t === 'y') {
                  return (date.getFullYear() + '').substr(4 - all.length);
              }
              return all;
          });
          return format;
      }
      return dateFormat(value, arg);
    })
    var vm = new Vue({
      el: '#app',
      data: {
        date: new Date()
      }
    });
  </script>
</body>
</html>

生命周期过程
挂载(初始化相关属性)
beforeCreate
created
beforeMount
mounted
更新(元素或组件的变更操作)
beforeUpdate
updated
销毁(销毁相关属性)
beforeDestroy
destroyed

Vue实例生命周期图示

1、beforeCreate 在实例初始化之后,数据观测和事件配置之前被调用。
2、created 在实例创建完成后被立即调用。
3、beforeMount 在挂载开始之前被调用。
4、mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。
5、beforeUpdate 数据更新时调用,发生在虚拟DOM打补丁之前。
6、updated 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。
7、beforeDestroy 实例销毁之前调用。
8、destroyed 实例销毁后调用。
在这里插入图片描述
实例生命周期代码解释


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>{{msg}}</div>
    <button @click='update'>更新</button>
    <button @click='destroy'>销毁</button>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      Vue实例的生命周期
      
    */
    var vm = new Vue({
      el: '#app',
      data: {
        msg: '生命周期'
      },
      methods: {
        update: function(){
          this.msg = 'hello';
        },
        destroy: function(){
          this.$destroy();
        }
      },
      beforeCreate: function(){
        console.log('beforeCreate');
      },
      created: function(){
        console.log('created');
      },
      beforeMount: function(){
        console.log('beforeMount');
      },
      mounted: function(){
        console.log('mounted');
      },
      beforeUpdate: function(){
        console.log('beforeUpdate');
      },
      updated: function(){
        console.log('updated');
      },
      beforeDestroy: function(){
        console.log('beforeDestroy');
      },
      destroyed: function(){
        console.log('destroyed');
      }
    });
  </script>
</body>
</html>

数组相关API – 变异方法(会修改原始数组) 替换数组(会生成新的数组)
变异方法 (会修改原始数组):
pop()
push()
shif()
unshif()
splice()
sort()
reverse()

替换数组 (会生成新的数组):
filter()
concat()
slice()

案例如下:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <div>
      <span>
        <input type="text" v-model='fname'>
        <button @click='add'>添加</button>
        <button @click='del'>删除</button>
        <button @click='change'>替换</button>
      </span>
    </div>
    <ul>
      <li :key='index' v-for='(item,index) in list'>{{item}}</li>
    </ul>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      Vue数组操作
      1、变异方法:会影响数组的原始数据的变化。
      2、替换数组:不会影响原始的数组数据,而是形成一个新的数组。
    */
    var vm = new Vue({
      el: '#app',
      data: {
        fname: '',
        list: ['apple','orange','banana']
      },
      methods: {
        add: function(){
          this.list.push(this.fname);
        },
        del: function(){
          this.list.pop();
        },
        change: function(){
          this.list = this.list.slice(0,2);
        }
      }
    });
  </script>
</body>
</html>

动态响应式数据处理 vm.$set()
有三个参数:参数1 可以数组或者对象,参数2 名字或者索引,参数3value值
实例代码:


<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <ul>
      <li v-for='item in list'>{{item}}</li>
    </ul>
    <div>
      <div>{{info.name}}</div>
      <div>{{info.age}}</div>
      <div>{{info.gender}}</div>
    </div>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      动态处理响应式数据
      
    */
    var vm = new Vue({
      el: '#app',
      data: {
        list: ['apple', 'orange', 'banana'],
        info: {
          name: 'lisi',
          age: 12
        }
      },
    });
    // vm.list[1] = 'lemon';
    // Vue.set(vm.list, 2, 'lemon');
    vm.$set(vm.list, 1, 'lemon');

    // vm.info.gender = 'male';
    vm.$set(vm.info, 'gender', 'female');

    
  </script>
</body>
</html>

组件化
为什么要用组件:代码重用,功能重用

组件的注意事项:
使用关键字 componen 进行定义
data:必须是一个函数;
template:组件模板内容必须是单个根元素,组件模板内容可以是模板字符串 ``

组件命名规则: 对于下面两种方式,推荐用短横线方式
短横线方式:在这里插入代码片 Vue.component('my-component', { /* ... */ })
驼峰命名方式:Vue.component('MyComponent', { /* ... */ })
定义组件的语法:

 Vue.component(组件名称, {
   data: 组件数据,
   template: 组件模板内容
 })

注册一个名为button-content的组件

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>组件</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <button-content></button-content>
    </div>
    <script>
        // Vue.component(组件名称, {
        //     data: 组件数据,
        //     template: 组件模板内容
        // })

        Vue.component('button-content', {
            data: function() {
                return {
                    count: 0
                }
            },
            template: "<button @click='handle'>点击了{{count}}次</button>",
            methods: {
                handle: function() {
                    this.count += 2;
                }
            }
        })
        let vm = new Vue({
            el: "#app",
            data: {

            },
            methods: {

            }
        })
    </script>
</body>

</html>

局部组件注册

语法要求:

   var ComponentA = { /* ... */ }
   var ComponentB = { /* ... */ }
   var ComponentC = { /* ... */ }
   new Vue({
     el: '#app'
     components: {
       'component-a': ComponentA,
       'component-b': ComponentB,
       'component-c': ComponentC,
     }
   })

实例案例如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <hello-world></hello-world>
    <hello-tom></hello-tom>
    <hello-jerry></hello-jerry>
    <test-com></test-com>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      局部组件注册
      局部组件只能在注册他的父组件中使用
    */
    Vue.component('test-com',{
      template: '<div>Test<hello-world></hello-world></div>'
    });
    var HelloWorld = {
      data: function(){
        return {
          msg: 'HelloWorld'
        }
      },
      template: '<div>{{msg}}</div>'
    };
    var HelloTom = {
      data: function(){
        return {
          msg: 'HelloTom'
        }
      },
      template: '<div>{{msg}}</div>'
    };
    var HelloJerry = {
      data: function(){
        return {
          msg: 'HelloJerry'
        }
      },
      template: '<div>{{msg}}</div>'
    };
    var vm = new Vue({
      el: '#app',
      data: {
        
      },
      components: {
        'hello-world': HelloWorld,
        'hello-tom': HelloTom,
        'hello-jerry': HelloJerry
      }
    });
  </script>
</body>
</html>

组件间数据互传:
父组件向子组件传值:
1、组件内部通过 props 接收传递过来的值
props 的命名规则,在模板中需要使用 短横线格式,别的地方可以使用驼峰模式
props属性值类型:字符串 数值 布尔值 数组 对象

  Vue.component(‘menu-item', {
    props: ['title'],
    template: '<div>{{ title }}</div>'
  })

2、父组件通过属性将值传递给子最件

  <menu-item title="来自父组件的数据"></menu-item>
  <menu-item :title="title"></menu-item>

实例案例如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>父子组价间数据传输</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <div>{{pmsg}}</div>
        <text-title title="父组件本身自己的值"></text-title>
        <text-title :title="ptitle" content="hello"></text-title>

    </div>

    <script>
        Vue.component("text-title", {
            props: ["title", "content"],
            data: function() {
                return {
                    msg: "什么玩意啊"
                }
            },
            template: `<div>{{msg+"---"+title+"---"+content}}</div>`

            // msg是子组件本身的数据,直接在模板输出即可,不是子组件自身的数据,需要用 props 接收数据,同时也可以结合v-bind进行动态属性绑定
        })
        let vm = new Vue({
            el: "#app",
            data: {
                pmsg: "父组件",
                ptitle: "父组件的标题"
            },
            methods: {

            }
        })
    </script>
</body>

</html>

子组件向父组件传值
1、子组件通过自定义事件向父组件传递数据
同时还可以进行传参

  <button v-on:click='$emit("enlarge-text") '>扩大字体</button>

2、父组件监听子组件的事件

  <menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>

实例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>子组件向父组件传值</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">

        <p :style="{fontSize:fSize+ 'px'}">{{pmsg}}</p>
        <menu-list :list="list" @enlarge-text="handle"></menu-list>
    </div>

    <script>
        Vue.component("menu-list", {
            props: ["list"],
            data: function() {
                return {

                }
            },
            template: `<div>
            <ul>
                <li :key="index" v-for="(item,index) in list">{{item}}</li>
            </ul>    
            <button @click="$emit('enlarge-text')"> 变粗变大 </button>
            </div>
            `
        })
        let vm = new Vue({
            el: "#app",
            data: {
                pmsg: "看我变粗变大",
                list: ["orange", "banana", "apple"],
                fSize: 10
            },
            methods: {
                handle: function() {
                    this.fSize += 5;
                }
            }
        })
    </script>
</body>

</html>

组件插槽
父组件向子组件传递内容

  <slot></slot>   插槽你  占位标签

1、插槽位置:

  Vue.component('alert-box', {
    template: `
      <div class="demo-alert-box">
        <strong>Error!</strong>
        <slot></slot>
      </div>
    `
  })

2、插槽内容

  <alert-box>Something bad happened.</alert-box>

基本用法案例

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <alert-box>有bug发生</alert-box>
    <alert-box>有一个警告</alert-box>
    <alert-box></alert-box>
  </div>
  <script type="text/javascript" src="js/vue.js"></script>
  <script type="text/javascript">
    /*
      组件插槽:父组件向子组件传递内容
    */
    Vue.component('alert-box', {
      template: `
        <div>
          <strong>ERROR:</strong>
          <slot>默认内容</slot>
        </div>
      `
    });
    var vm = new Vue({
      el: '#app',
      data: {
        
      }
    });
  </script>
</body>
</html>

具名插槽

就是让相应的内容进到相应的标签中
1、插槽定义

<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>

2、插槽内容

<base-layout>
  <h1 slot="header">标题内容</h1>
  
  <p>主要内容1</p>
  <p>主要内容2</p>

  <p slot="footer">底部内容</p>
</base-layout>

实例代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>具名插槽</title>
    <script src="vue.js"></script>
</head>

<body>
    <div id="app">
        <base-layout>
            <p slot="header">头部</p>
            <p>内容1</p>
            <p>内容2</p>
            <p slot="footer">尾部</p>
        </base-layout>

        <base-layout>
            <template slot="header">
                    <p>头部</p>
            </template>
            <template>
                    <p>内容2</p>
            </template>
            <template slot="footer">
                    <p>尾部</p>
            </template>

        </base-layout>

    </div>

    <script>
        Vue.component("base-layout", {
            props: [],
            data: function() {
                return {

                }
            },
            template: `<div>
                <header>
                    <slot name="header"></slot>
                </header>
                <main>
                    <slot></slot>
                </main>
                <footer>
                    <slot name="footer"></slot>
                </footer>
            </div>`
        })
        let vm = new Vue({
            el: "#app",
            data: {

            },
            methods: {

            }
        })
    </script>
</body>

</html>

作用域插槽
主要应用场景:父组件要对子组件的内容进行加工处理
在子组件中 通过属性绑定把需要处理的内容上送到父组件中
在父组件中通过定义属性 slot-scope=“slotScope” 进行上送的内容处理
1、插槽定义

 <ul>
   <li v-for= "item in list" v-bind:key= "item.id" >
      <slot v-bind:item="item">
        {{item.name}}
      </slot>
   </li>
 </ul>

2、插槽内容

  <fruit-list v-bind:list= "list">
    <template slot-scope="slotProps">
      <strong v-if="slotProps.item.current">
         {{ slotProps.item.text }}
      </strong>
    </template>
  </fruit-list>

实例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>作用域插槽用法</title>
    <style type="text/css">
        .current {
            color: orange;
        }
    </style>

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

<body>
    <div id="app">
        <fruit-list :list="list">
            <template slot-scope="slotScope">
                <strong v-if="slotScope.info.id===3" class="current">{{slotScope.info.name}}</strong>
                <span v-else>{{slotScope.info.name}}</span>
            </template>

        </fruit-list>

    </div>

    <script>
        Vue.component("fruit-list", {
            props: ["list"],
            data: function() {
                return {

                }
            },
            template: `
                <div>
                    <ul>
                        <li :key="item.id" v-for="(item,index) in list">
                        <slot :info="item">{{item.name}}</slot>  // 对item进行动态属性绑定,上送父组件
                        </li>
                    </ul>
                </div>
            `
        })
        let vm = new Vue({
            el: "#app",
            data: {
                list: [{
                    id: 1,
                    name: 'apple'
                }, {
                    id: 2,
                    name: 'orange'
                }, {
                    id: 3,
                    name: 'banana'
                }]
            },
            methods: {

            }
        })
    </script>
</body>

</html>

前后端交互
在Vue之前我们通过ajax和后台数据交互,但是ajax技术现在有点落后了,我们此时介绍Vue中新的前后端交互的技术
复习:
原生ajax请求:

1、var xhr = new XMLHttpRequest();
2、xhr.open("get","http://locahost:3000?uname=ls&age=12");
3、xhr.setRequestHeader("Content-Type":"lication/x-www-form-urlenlode");
4、xhr.send(null)
响应设置
xhr.onreadystatechange=function(){
if(xhr.status===200&&xhr.readystate===4){
			xhr.responseText
	}
}

url地址传参格式:
1、传统URL格式:http://127.0.0.1:3000?uname=lisi&age=12
2、Restful格式:http://127.0.0.1:3000/:id

js中常见的异步调用:
1、定时器
2、ajax
3、时间函数

在ajax中存在什么问题:
对于多个ajax请求时,由于回调时间不确定,数据返回没有顺序,会造成混乱 ,如果解决这个问题,需要使用嵌套关系,这样会造成回调地狱

回调地狱实例

    $.ajax({
      url: 'http://localhost:3000/data',
      success: function(data) {
        console.log(data)
        $.ajax({
          url: 'http://localhost:3000/data1',
          success: function(data) {
            console.log(data)
            $.ajax({
              url: 'http://localhost:3000/data2',
              success: function(data) {
                console.log(data)
              }
            });
          }
        });
      }
    });
    

为了解决ajax的回调地狱,我们引进了 Promise 实例对象 ,同时也让异步请求的语法更加简洁

Promise的基本用法
1、如何定义一个Promise实例:我们使用new来创建一个Promise 实例对象 ,接收两个
参数,是函数,两个参数是 resolve 和 reject 两个参数分别表示异步操作执行成功之后
的回调函数 和 异步操作失败执行之后的回调函数
2、Promise 实例生成之后,可以使用then方法 里面包含函数 指定 resolve状态 和 reject状态的回调函数 , 通过then 来保证异步执行返回的数据的顺序,
then的返回值:
1、可以返回一个非Promise对象
2、可以返回一个Promise对象

实例代码:

    <!DOCTYPE html>
    <html lang="en">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Promise基本使用</title>
    </head>

    <body>

        <script>
            var p = new Promise(function(resolve, reject) {
                // 我们通过定时器实现异步的任务
                setTimeout(() => {
                    var flag = true;
                    if (flag) {
                        // 执行正常情况
                        resolve("hello");
                    } else {
                        // 异常情况
                        reject("error");
                    }
                }, 1000);
            });
         p.then(function(data) {
                // 接收正常情况的数据
                console.log(data);
            }),
            function(info) {
                // 接收异常情况的数据
                console.log(info);
            }
        </script>
    </body>

    </html>

Promise的实例方法:
1、then — 得到异步任务的正确结果
2、catch — 获取异常信息
3、finnal — 任务执行成功与否都执行(还是非标准)

以上三个方法都是Promise 的实例上的方法
Promise的实例对象方法

Promise的对象方法:
1、all — 执行成功之后返回的所有的数据
2、race – 执行成功第一个返回的数据,后续返回的不在接收

实例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>

    <script type="text/javascript">
        /*
              Promise常用API-对象方法
            */
        // console.dir(Promise)
        function queryData(url) {
            return new Promise(function(resolve, reject) {
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function() {
                    if (xhr.readyState != 4) return;
                    if (xhr.readyState == 4 && xhr.status == 200) {
                        // 处理正常的情况
                        resolve(xhr.responseText);
                    } else {
                        // 处理异常情况
                        reject('服务器错误');
                    }
                };
                xhr.open('get', url);
                xhr.send(null);
            });
        }

        var p1 = queryData('http://localhost:3000/a1');
        var p2 = queryData('http://localhost:3000/a2');
        var p3 = queryData('http://localhost:3000/a3');
        Promise.all([p1, p2, p3]).then(function(result) {
                console.log(result)
            })
            // Promise.race([p1,p2,p3]).then(function(result){
            //   console.log(result)
            // })
    </script>
</body>

</html>

Fetch的基本使用
1、Fetch就是ajax + Promise结合使用的方式 和$ajax()差不多
2、Fetch默认请求是get
3、使用fetch时使用text接收后台返回的数据
4、fetch使用method进行请求方式的设置
5、对于post请求方式时使用body进行数据传递
6、对于post请求方式时使用headers进行请求头设置
7、DELETE请求方式参数传递 和 get一样
8、用fetch获取的数据,如果响应正常返回,我们首先看到的是response对象,此时就需要我们收到数据后 调用相应的方法将其转换为相应格式的数据,比如 json text blob等等
fetch使用的案例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Fetch的基本使用</title>
</head>

<body>
    <!-- 就是ajax和Promise 结合使用的方式 -->

    <script>
        // get传递数据===传统url方式
        // fetch("http://localhost:3000/books?id=123", {
        //     method: "get",
        // }).then(function(data) {

        //     // text()是 fetch的一部分,他返回Promise的实例对象,用于获取后台返回的数据
        //     return data.text();
        // }).then(function(data) {
        //     console.log(data);
        // })

        // // get传递数据===restfulF方式传递url的数据
        // fetch("http://localhost:3000/books/456", {
        //     method: "get",
        // }).then(function(data) {

        //     // text()是 fetch的一部分,他返回Promise的实例对象,用于获取后台返回的数据
        //     return data.text();
        // }).then(function(data) {
        //     console.log(data);
        // })

        // Delete方式请求方式数据传递
        // fetch('http://localhost:3000/books/789', {
        //         method: "delete",
        //     })
        //     .then(function(data) {
        //         return data.text();
        //     }).then(function(data) {
        //         console.log(data);
        //     })

        // ----------------------------------

        // post请求方式传递数据
        // fetch("http://localhost:3000/books", {
        //         method: "post",
        //         body: "uname=lisi&pwd=123",
        //         headers: {
        //             "Content-Type": "application/x-www-form-urlencoded"
        //         }
        //     })
        //     .then(function(data) {
        //         return data.text();
        //     }).then(function(data) {
        //         console.log(data)
        //     })
        // post请求方式使用json传递数据
        // fetch("http://localhost:3000/books", {
        //         method: "post",
        //         body: JSON.stringify({
        //             uname: "lisi",
        //             pwd: "123"
        //         }),
        //         headers: {
        //             "Content-Type": "application/json"
        //         }
        //     })
        //     .then(function(data) {
        //         return data.text();
        //     }).then(function(data) {
        //         console.log(data)
        //     })
        // put请求方式传递参数
        fetch("http://localhost:3000/books/123", {
                method: "put",
                body: JSON.stringify({
                    uname: "王二麻子",
                    pwd: "12345678"
                }),
                headers: {
                    "Content-Type": "application/json"
                }
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data);
            })
                    // put请求方式传递参数
        fetch("http://localhost:3000/books/123", {
                method: "put",
                body: "uname=lisi&pwd=123",
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded"
                }
            })
            .then(function(data) {
                return data.text();
            }).then(function(data) {
                console.log(data);
            })
    </script>
</body>

</html>

axios的基本用法
axions的优点:
1、基于promise用于浏览器和nodeJs的http客户端
2、支持浏览器和nideJs
3、支持promise
4、能拦截请求和响应
5、自动转换json数据
6、能转换请求和响应数据
7、then接收的数据是个Object
8、其中axios有一个data属性是固定用法,用于获取后台的实际数据
9、DELETE请求方式参数传递 和 get一样

get post delete put 传递参数实例案例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>axios的基本用法</title>
</head>

<body>
    <script src="js/axios.js"></script>
    <script>
        // axios的get传统url传递数据
        // axios.get("http://localhost:3000/axios?id=123").then(function(ret) {
        //         // console.log(ret);
        //         console.log(ret.data)
        //     })

        // axios的get restful形式传递数据
        // axios.get("http://localhost:3000/axios/123").then(function(ret) {
        //     // console.log(ret);
        //     console.log(ret.data)
        // })

        // axios的get 通过params设置id传递数据
        // axios.get("http://localhost:3000/axios", {
        //         params: {
        //             id: 789
        //         }
        //     })
        //     .then(function(ret) {
        //         console.log(ret.data)
        //     })

        // axios的delete 通过params设置id传递数据
        // axios.delete("http://localhost:3000/axios", {
        //         params: {
        //             id: 789
        //         }
        //     })
        //     .then(function(ret) {
        //         console.log(ret.data)
        //     })

        // axiosde post请求方式进行数据传递
        // axios.post("http://localhost:3000/axios", {
        //     uname: "zs",
        //     pwd: "123"
        // }).then(function(ret) {
        //     console.log(ret.data)
        // })

        // axios的post请求方式使用URLSearchParams()进行传递数据
        // var params = new URLSearchParams();
        // params.append("uname", "zs");
        // params.append("pwd", "123456");
        // axios.post("http://localhost:3000/axios", params).then(function(ret) {
        //     console.log(ret.data)
        // })

        axios.put("http://localhost:3000/axios/123", {
            uname: "秀儿",
            pwd: "23456"
        }).then(function(ret) {
            console.log(ret.data);
        })
    </script>
</body>

</html>

axios 的响应结果和全局配置
响应结果:
1、data是实际响应返回回来的数据
2、headers 是设置的请求头
3、status 是响应状态码
全局设置:
1、配置公共的请求地址URL:axios.defaults.baseURL
2、配置超时时间;axios.defaults.timeout
3、配置公共的请求头:axios.defaults.headers[“mytoken”]=“ok”

实例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>axios的响应结果和全局配置</title>
    <script src="js/axios.js"></script>
</head>

<body>
    <script>
        axios.get("http://localhost:3000/axios-json").then(function(ret) {
            // console.log(ret.data)   //得到的是一个对象
            console.log(ret.data.uname)
        })

        // 全局配置url地址
        axios.defaults.baseURL = "http://localhost:3000/";
        // 设置请求头信息
        axios.defaults.headers["mytoken"] = "hello";
        axios.get("axios-json").then(function(ret) {
            console.log(ret.data.uname)
        })
    </script>
</body>

</html>

axios拦截器的用法:
请求拦截器:
1、作用是在请求发送前进行的一些操作
2、例如 在每个请求体中加上 token,统一做了处理如果以后要改也非常容易
响应拦截器:
1、作用是在接收到响应之后进行的一些操作
2、例如在服务器登录状态失效后,需要重新登录的时候,跳转到登录页面
实例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>axios拦截器</title>
    <script src="js/axios.js"></script>
</head>

<body>

    <script>
        axios.interceptors.request.use(function(config) {
                console.log(config.url); // 监听的是下面的get地址
                config.headers.mytoken = "nihao"
                return config;
            }),
            function(err) {
                console.log(err)
            }

        axios.interceptors.response.use(function(res) {
                console.log(res)
                var data = res.data;
                return data;
            }),
            function(err) {
                console.log(err)
            }

        axios.get("http://localhost:3000/adata").then(function(data) {
            console.log(data);
        })
    </script>
</body>

</html>

async和await用法:
async和await 主要是处理异步操作
1、async作为一个关键字放在函数的前面
2、任何一个async都会返回隐式返回一个promise
3、await关键字只能在使用了async定义的函数中使用
4、await后面可以直接跟一个promise实例对象
5、async和await让异步代码看起来、表现起来更像同步代码
6、await函数不能单独使用,而且async函数返回的是一个Promise对象,可以使用then函数添加回调函数。当函数执行的时候,一旦遇到await函数就会先返回一个Promise对象,等到异步操作完成,再去执行后面的语句

代码实例:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>async和await的用法</title>
    <script src="js/axios.js"></script>

</head>

<body>
    <script>
        axios.defaults.baseURL = "http://localhost:3000";
        // axios.get("adata").then(function(ret) {
        //     console.log(ret.data);
        // })

        // async function queryData() {
        //     var ret = await axios.get("adata");
        //     // console.log(ret.data);
        //     return ret.data;
        // };
        // queryData().then(function(data) {
        //     console.log(data);
        // })

        async function queryData() {
            var ret = await new Promise(function(resolve, reject) {
                setTimeout(() => {
                    resolve("nihao");
                }, 1000);
            });
            return ret;
        };
        queryData().then(function(ret) {
            console.log(ret);
        })
    </script>
</body>

</html>

async和await处理多个异步任务:

前端路由:
首先后端路由:
1、根据不同的用户URL地址,返回不同的内容
2、URL请求地址与服务器资源之间的对应关系
总结:后端路由就是根据不同的URL地址分发不同的资源

前端路由:
1、SPA:单页面应用程序,整个网站只有一个页面,页面内容发生变化,通过ajax局部更新实现,同时支持浏览器的前进和后退
2、SPA实现原理:基于URL的hash(hash变化不会刷新页面,不会触发新的url地址请求),但是在实现hash过程中 ,最核心的技术点就是前端路由
3、根据不同的用户事件,显示不同的页面内容
4、用户事件和时间处理函数之间的对应关系
总结:前端路由负责事件的监听,触发事件后,通过事件函数渲染不同的内容

监听hash的事件是window的onhashchange事件,根据获取到的最新hash值,切换要显示的组件的名称
同过location.hash获取到最新的hash值

Vue.Router 是Vue.js的官方路由管理器,包含的功能:
1.支持html历史模式和hash模式
2.支持嵌套路由
3.支持路由参数
4.支持编程式路由
5.支持命名路由

路由的基本使用步骤:
1、引入路由的js库文件
2、添加路由连接链接 <router-link to="/user">User</router-link>
3、添加路由占位符<router-view></router-view>
4、定义路由组件

  var User = {
     template: '<div>User</div>'
  }
  var Register = {
     template: '<div>Register</div>'
  }

5、配置路由规则并创建路由实例

  // 创建路由实例对象  
  var router = new VueRouter({
    // routes 是路由规则数组
    routes: [
      // 每个路由规则都是一个配置对象,其中至少包含 path 和 component 两个属性:
      // path 表示当前路由规则匹配的 hash 地址
      // component 表示当前路由规则对应要展示的组件
      {path:'/user',component: User},
      {path:'/register',component: Register}
    ]
  })

6、把路由挂载到Vue根实例中

  new Vue({
     el: '#app',
     // 为了能够让路由规则生效,必须把路由对象挂载到 vue 实例对象上
     router
  });

路由重定向:通过路由规则的 redirect 属性,指定一个新的路由地址,可以很方便地设置路由的重定向:其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向到的新地址

实例代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>路由的基本使用</title>
    <script src="js/vue_2.5.22.js"></script>
    <script src="js/vue-router_3.0.2.js"></script>
</head>

<body>
    <div id="app">
        <router-link to="/user">User</router-link>
        <router-link to="/register">Register</router-link>

        <!-- 路由占位符 -->
        <router-view></router-view>

    </div>

    <script>
        var User = {
            template: `<div>User 组件</div>`
        }
        var Register = {
            template: `<div>Register 组件</div>`
        }

        // 创建路由实例对象
        var router = new VueRouter({
            // routers是路由规则数组
            routes: [
                // 每个路由都是一个规则对象,都由path 和component两个属性
                // path表示当前路由匹配的hash地址
                // componment表示当前路由规则要展示的组件

                // redirect 重定向, 将请求的地址重新定向到一个新的路由地址
                // 其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向到的新地址
                {
                    path: "/",
                    redirect: "/user"
                }, {
                    path: "/user",
                    component: User
                }, {
                    path: "/register",
                    component: Register
                }
            ]
        });
        let vm = new Vue({
            el: "#app",
            data: {

            },
            methods: {

            },
            // 必须将创建的路由实例对象 挂载带Vue的根实例下
            router
        })
    </script>
</body>

</html>

路由嵌套:
1、点击父路由链接显示模板内容
2、模板内容有子路由链接
3、点击子路由链接显示子路由模板内容
步骤:
1、在需要进行添加的子路由 的父路由组件里添加 相应的设置 添加占位符
2、添加子路由的组件
3、在父路由的规则中利用 children 属性设置子路由的对应关系

实例代码:

<body>
    <div id="app">
        <router-link to="/user">User</router-link>
        <router-link to="/register">Register</router-link>

        <!-- 路由占位符 -->
        <router-view></router-view>

    </div>

    <script>
        var User = {
            template: `<div>User 组件</div>`
        }
        var Register = {
            template: `<div>
                    <h1>Register 组件</h1>
                    <router-link to="/register/tab1">Tab1</router-link>
                    <router-link to="/register/tab2">Tab2</router-link>
                <hr />
                    <router-view />
                </div>`
        }

        var Tab1 = {
            template: `<h1>
                    tab1 子组件
                </h1>`
        }
        var Tab2 = {
                template: `<h1>
                    tab2 子组件
                </h1>`
            }
            // 创建路由实例对象
        var router = new VueRouter({
            // routers是路由规则数组
            routes: [
                // 每个路由都是一个规则对象,都由path 和component两个属性
                // path表示当前路由匹配的hash地址
                // componment表示当前路由规则要展示的组件

                // redirect 重定向, 将请求的地址重新定向到一个新的路由地址
                // 其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向到的新地址
                {
                    path: "/",
                    redirect: "/user"
                }, {
                    path: "/user",
                    component: User
                }, {
                    path: "/register",
                    component: Register,
                    children: [{
                        path: "/register/tab1",
                        component: Tab1
                    }, {
                        path: "/register/tab2",
                        component: Tab2
                    }]
                }
            ]
        });
        let vm = new Vue({
            el: "#app",
            data: {

            },
            methods: {

            },
            // 必须将创建的路由实例对象 挂载带Vue的根实例下
            router
        })
    </script>
</body>

动态匹配路由:
通过动态路由匹配进行参数的传递
1、动态匹配路由
2、使用props进行传参 方法一:props:true
3、props为一个对象可以直接传递对象,但是无法传递url中的id
4、props为一个箭头函数,可以传递参数和url中 的id
实例代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>路由的基本使用</title>
    <script src="js/vue_2.5.22.js"></script>
    <script src="js/vue-router_3.0.2.js"></script>
</head>

<body>
    <div id="app">
        <router-link to="/user/1">User1</router-link>
        <router-link to="/user/2">User2</router-link>
        <router-link to="/user/3">User3</router-link>
        <router-link to="/user/4">User4</router-link>
        <router-link to="/register">Register</router-link>

        <!-- 路由占位符 -->
        <router-view></router-view>

    </div>

    <script>
        var User = {
            // props: ["id"], // 使用props 接收路由传参

            props: ["id", "uname", "age"], // 使用props 接收路由传参
            // 组件中通过 $route.params.id 可以获取传的url中的ID值
            // template: `<div>User 组件 + {{$route.params.id}}</div>`
            // template: `<div>User 组件用户ID:{{id}}</div>`

            template: `<div>User 组件用户ID:{{id}}----{{uname}}-----{{age}}</div>`


        }
        var Register = {
            template: `<div>
                    <h1>Register 组件</h1>
                    <router-link to="/register/tab1">Tab1</router-link>
                    <router-link to="/register/tab2">Tab2</router-link>
                <hr />
                    <router-view />
                </div>`
        }

        var Tab1 = {
            template: `<h1>
                    tab1 子组件
                </h1>`
        }
        var Tab2 = {
                template: `<h1>
                    tab2 子组件
                </h1>`
            }
            // 创建路由实例对象
        var router = new VueRouter({
            // routers是路由规则数组
            routes: [
                // 每个路由都是一个规则对象,都由path 和component两个属性
                // path表示当前路由匹配的hash地址
                // componment表示当前路由规则要展示的组件

                // redirect 重定向, 将请求的地址重新定向到一个新的路由地址
                // 其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向到的新地址
                {
                    path: "/",
                    redirect: "/user"
                }, {
                    path: "/user/:id",
                    component: User,
                    // 使用 props 代替 $route.params 直接传参,在组件中同样使用 props 接收
                    // props: true

                    // props: {
                    //     "uname": "lisi",
                    //     "age": 12
                    // } // props设置为一个对象进行传递路由参数

                    props: route => ({
                        "uname": "wangwang",
                        "age": 12,
                        id: route.params.id
                    })
                }, {
                    path: "/register",
                    component: Register,
                    children: [{
                        path: "/register/tab1",
                        component: Tab1
                    }, {
                        path: "/register/tab2",
                        component: Tab2
                    }]
                }
            ]
        });
        let vm = new Vue({
            el: "#app",
            data: {

            },
            methods: {

            },
            // 必须将创建的路由实例对象 挂载带Vue的根实例下
            router
        })
    </script>
</body>

</html>

命名路由
作用不大,就是为了更加方便的表示路由的路径,为路由起一个别名
使用方法如下:

  const router = new VueRouter({
    routes: [
      {
        path: '/user/:id',
        name: 'user',
        component: User
      }
    ]
  })

在路由连接和编程式导航中的使用方法:

  <router-link :to="{ name: 'user', params: { id: 123 }}">User</router-link>
  router.push({ name: 'user', params: { id: 123 }})

编程式导航:
页面导航有两种方式:
1、声明式导航:通过点击连接进行跳转的 比如 a 标签 就是声明式导航
2、编程式导航:通过调用JavaScript的api实现导航的方式,如location.href
3、对于编程式导航,常用的api有:

this.$router.push("hash地址")
this.$router.go(n)

go(1) ---- 在历史页面前进
go(-1) ---- 在历史页面后退

实现步骤:
1、在需要进行编程式导航的组件中进行时间绑定
2、在组件中定义methods方法,进行相应操作

代码实现:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>路由的基本使用</title>
    <script src="js/vue_2.5.22.js"></script>
    <script src="js/vue-router_3.0.2.js"></script>
</head>

<body>
    <div id="app">
        <router-link to="/user">User</router-link>
        <router-link to="/register">Register</router-link>

        <!-- 路由占位符 -->
        <router-view></router-view>

    </div>

    <script>
        var User = {
            template: `<div>
                <button @click="gogo">User 组件</button>
                </div>`,
            methods: {
                gogo: function() {
                    this.$router.push("/register")
                }
            }
        }
        var Register = {
            template: `<div>
                <h1>Register 组件</h1>
                <button @click="goBack">回退</button>
                </div>`,
            methods: {
                goBack: function() {
                    this.$router.go(-1);
                }
            }
        }

        // 创建路由实例对象
        var router = new VueRouter({
            // routers是路由规则数组
            routes: [
                // 每个路由都是一个规则对象,都由path 和component两个属性
                // path表示当前路由匹配的hash地址
                // componment表示当前路由规则要展示的组件

                // redirect 重定向, 将请求的地址重新定向到一个新的路由地址
                // 其中,path 表示需要被重定向的原地址,redirect 表示将要被重定向到的新地址
                {
                    path: "/",
                    redirect: "/user"
                }, {
                    path: "/user",
                    component: User
                }, {
                    path: "/register",
                    component: Register
                }
            ]
        });
        let vm = new Vue({
            el: "#app",
            data: {

            },
            methods: {

            },
            // 必须将创建的路由实例对象 挂载带Vue的根实例下
            router
        })
    </script>
</body>

</html>

$router.push()方法还有很多规则
都可以进行相应的跳转

// 字符串(路径名称)
  router.push('/home')
  // 对象
  router.push({ path: '/home' })
  // 命名的路由(传递参数)
  router.push({ name: '/user', params: { userId: 123 }})
  // 带查询参数,变成 /register?uname=lisi
  router.push({ path: '/register', query: { uname: 'lisi' }})

前端工程化
模块化的好处:
1、模块化开发的好处:方便代码的重用,从而提升开发效率,并且方便后期的维护
2、模块化就是把单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成员,也可以依赖别的模块

浏览器端模块化规范:
1、AMD规范,主要体现是 require.js
2、CMD规范:主要体现是sea.js

服务器端模块化规范:
主要是 commonJs
1、模块分为单文件模块和 包
2、模块成员导出:module.exports 和exports
3、模块成员导入:require(“模块标识符”)

ES6模块化规范:
1、每个js都是一个独立的模块
2、导入模块成员使用 import 关键字
3、暴露模块成员使用 export 关键字

在nodeJs中通过babel体验ES6模块化
使用步骤:固定用法 首先 npm init -y 初始化项目
1、npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node
2、npm install --save @babel/polyfill
3、项目跟目录创建文件 babel.config.js
4、设置 babel.config.js 文件内容如右侧代码

  const presets = [
    ["@babel/env", {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1"
      }
    }]
  ];
  module.exports = { presets };

5、通过 npx babel-node index.js 执行代码

ES6模块化的基本语法
默认导出和默认导入
1、默认导出使用 export.default + 默认导出的成员
2、默认导入使用import 接收名称 from “模块标识符”
注意:每个模块中,只允许使用唯一的一次 export default,否则会报错!

按需导出和按需导入
1、按需导出语法 export let a = 20
2、按需导入语法 import {a} from “默认标示”
注意:每个模块中,可以使用多次按需导出

直接导入并执行模块代码
用法: // 直接导入并执行模块代码
import ‘./m2.js’
直接使用import “模块标识符”

webpack的介绍和用法
**作用:**进行代码打包,性能优化,代码压缩等等
**优点:**webpack 提供了友好的模块化支持,以及代码压缩混淆、处理 js 兼容问题、性能优化等强大的功能,从而让程序员把工作的重心放到具体的功能实现上,提高了开发效率和项目的可维护性。

基本使用步骤:
1、使用 npm init -y 初始化项目
2、新建src源代码目录
3、新建src =>index.html 首页
4、初始化首页结构
5、运行 npm install jquery 命令,安装 jquery
在index.js中写好样式,引入html样式中,发现不行。此时我们需要进行webpack进行打包
webpack打包基本步骤:
1、运行 npm install webpack webpack-cli –D 命令,安装 webpack 相关的包
2、在项目根目录中,创建名为 webpack.config.js 的 webpack 配置文件
3、在 webpack 的配置文件中,初始化如下基本配置:

module.exports = {
  mode: 'development' // mode 用来指定构建模式
}

4、在 package.json 配置文件中的 scripts 节点下,新增 dev 脚本如下:

"scripts": {
 "dev": "webpack" // script 节点下的脚本,可以通过 npm run 执行
}

5、 在终端中运行 npm run dev 命令,启动 webpack 进行项目打包。

配置打包的入口和出口
1、打包的入口:src -> index.js
2、打包的出口:dist -> main.js

需要在 webpack.config.js 中新增如下配置信息:

const path = require('path') // 导入 node.js 中专门操作路径的模块
module.exports = {
  entry: path.join(__dirname, './src/index.js'), // 打包入口文件的路径
  output: {
    path: path.join(__dirname, './dist'), // 输出文件的存放路径
    filename: 'bundle.js' // 输出文件的名称
  }
}

配置webpack的自动打包功能
1、运行 npm install webpack-dev-server –D 命令,安装支持项目自动打包的工具
2、修改 package.json -> scripts 中的 dev 命令如下:

"scripts": {
  "dev": "webpack-dev-server" // script 节点下的脚本,可以通过 npm run 执行
}

3、将 src -> index.html 中,script 脚本的引用路径,修改为 "/buldle.js“
4、运行 npm run dev 命令,重新进行打包
5、在浏览器中访问 http://localhost:8080 地址,查看自动打包效果

注意:
1、webpack-dev-server 会启动一个实时打包的 http 服务器
2、webpack-dev-server 打包生成的输出文件,默认放到了项目根目录中,而且是虚拟的、看不见的

配置 html-webpack-plugin 生成预览页面
1、运行 npm install html-webpack-plugin –D 命令,安装生成预览页面的插件
2、修改 webpack.config.js 文件头部区域,添加如下配置信息:

// 导入生成预览页面的插件,得到一个构造函数
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin({ // 创建插件的实例对象
  template: './src/index.html', // 指定要用到的模板文件
  filename: 'index.html' // 指定生成的文件的名称,该文件存在于内存中,在目录中不显示
})

3、修改 webpack.config.js 文件中向外暴露的配置对象,新增如下配置节点:

module.exports = {
  plugins: [ htmlPlugin ] // plugins 数组是 webpack 打包期间会用到的一些插件列表

4、新启动打包 npm run dev

配置自动打包相关参数,启动打包之后自动打开浏览器

// package.json中的配置
  // --open 打包完成后自动打开浏览器页面
  // --host 配置 IP 地址
  // --port 配置端口
  "scripts": {
    "dev": "webpack-dev-server --open --host 127.0.0.1 --port 8888"
  },

由于webpack打包机制,只对js文件才能打包处理,对于css less sass 图片 文字 如果需要打包,此时需要进行loader加载器 处理
loader 加载器可以协助 webpack 打包处理特定的文件模块,比如:
1、less-loader 可以打包处理 .less 相关的文件
2、sass-loader 可以打包处理 .scss 相关的文件
3、 url-loader 可以打包处理 css 中与 url 路径相关的文件

打包处理css文件
1、运行 npm i style-loader css-loader -D 命令,安装处理 css 文件的 loader
2、在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

 // 所有第三方文件模块的匹配规则
  module: {
    rules: [
      { test: /\.css$/, use: ['style-loader', 'css-loader'] }
    ]
  }

3、其中,test 表示匹配的文件类型, use 表示对应要调用的 loader

注意:
use 数组中指定的 loader 顺序是固定的
多个 loader 的调用顺序是:从后往前调用

打包处理less文件
1、运行 npm i less-loader less -D 命令
2、在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

// 所有第三方文件模块的匹配规则
  module: {
    rules: [
      { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }
    ]
  }

打包scss文件
1、运行 npm i sass-loader node-sass -D 命令
2、在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

// 所有第三方文件模块的匹配规则
  module: {
    rules: [
      { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }
    ]
  }

配置postCSS自动添加css的兼容前缀
1、运行 npm i postcss-loader autoprefixer -D 命令
2、在项目根目录中创建 postcss 的配置文件 postcss.config.js,并初始化如下配置:

const autoprefixer = require('autoprefixer') // 导入自动添加前缀的插件
  module.exports = {
    plugins: [ autoprefixer ] // 挂载插件
  }

3、 webpack.config.js 的 module -> rules 数组中,修改 css 的 loader 规则如下:

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

打包样式表中的图片和字体文件
1、运行 npm i url-loader file-loader -D 命令
2、在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下:

 module: {
    rules: [
      { 
        test: /\.jpg|png|gif|bmp|ttf|eot|svg|woff|woff2$/, 
        use: 'url-loader?limit=16940'
      }
    ]
  }

3、其中 ? 之后的是 loader 的参数项。
limit 用来指定图片的大小,单位是字节(byte),只有小于 limit 大小的图片,才会被转为 base64 图片

打包处理js文件中的高级语法
1、安装babel转换器相关的包:npm i babel-loader @babel/core @babel/runtime -D
2、安装babel语法插件相关的包:npm i @babel/preset-env @babel/plugin-transform-runtime @babel/plugin-proposal-class-properties –D
3、在项目根目录中,创建 babel 配置文件 babel.config.js 并初始化基本配置如下:

module.exports = {
    presets: [ '@babel/preset-env' ],
    plugins: [ '@babel/plugin-transform-runtime', '@babel/plugin-proposal-class-properties’ ]
  }

4、在 webpack.config.js 的 module -> rules 数组中,添加 loader 规则如下

// exclude 为排除项,表示 babel-loader 不需要处理 node_modules 中的 js 文件
  { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }

Vue单文件组件
1、template 组件的模板区域
2、script 业务逻辑区域
3、style 样式区域

代码实例:

  <template>
    <!-- 这里用于定义Vue组件的模板内容 -->
  </template>

  <script>
    // 这里用于定义Vue组件的业务逻辑
    export default {
      data: () { return {} }, // 私有数据
      methods: {} // 处理函数
      // ... 其它业务逻辑
    }
  </script>

  <style scoped>
    /* 这里用于定义组件的样式 */
  </style>

webpack中配置vue组件的加载器
1、运行 npm i vue-loader vue-template-compiler -D 命令
2、在 webpack.config.js 配置文件中,添加 vue-loader 的配置项如下:

const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
  module: {
    rules: [
      // ... 其它规则
      { test: /\.vue$/, loader: 'vue-loader' }
    ]
  },
  plugins: [
    // ... 其它插件
    new VueLoaderPlugin() // 请确保引入这个插件!
  ]
}

在webpack项目中使用vue
1、运行 npm i vue –S 安装 vue
2、在 src -> index.js 入口文件中,通过 import Vue from ‘vue’ 来导入 vue 构造函数
3、创建 vue 的实例对象,并指定要控制的 el 区域
4、通过 render 函数渲染 App 根组件
实例代码

// 1. 导入 Vue 构造函数
import Vue from 'vue'
// 2. 导入 App 根组件
import App from './components/App.vue'

const vm = new Vue({
  // 3. 指定 vm 实例要控制的页面区域
  el: '#app',
  // 4. 通过 render 函数,把指定的组件渲染到 el 区域中
  render: h => h(App)
})

webpack打包发布
1、上线之前需要通过webpack将应用进行整体打包,可以通过 package.json 文件配置打包命令:
实例代码:

 // 在package.json文件中配置 webpack 打包命令
   // 该命令默认加载项目根目录中的 webpack.config.js 配置文件
   "scripts": {
     // 用于打包的命令
     "build": "webpack -p",
     // 用于开发调试的命令
     "dev": "webpack-dev-server --open --host 127.0.0.1 --port 3000",
   },

Vue脚手架
vue脚手架用于快速生成Vue项目基础结构
使用步骤
1、安装 3.x 版本的 Vue 脚手架: npm install -g @vue/cli
使用脚手架创建vue项目有三种模式
1、 // 1. 基于 交互式命令行 的方式,创建 新版 vue 项目
vue create my-project
2、 // 2. 基于 图形化界面 的方式,创建 新版 vue 项目
vue ui
3、 // 3. 基于 2.x 的旧模板,创建 旧版 vue 项目
npm install -g @vue/cli-init
vue init webpack my-project

脚手架生成的vue结构示意图:
在这里插入图片描述

Vue脚手架自定义属性:
通过vue.config.js来配置
1、在项目的跟目录创建文件 vue.config.js
在该文件中进行相关配置,从而覆盖默认配置

 // vue.config.js
  module.exports = {
    devServer: {
      port: 8888
    }
  }

Element-UI的基本使用
官网:官网http://element-cn.eleme.io/#/zh-CN
1、安装依赖包 npm i element-ui –S
2、导入 Element-UI 相关资源

// 导入组件库
  import ElementUI from 'element-ui';
  // 导入组件相关样式
  import 'element-ui/lib/theme-chalk/index.css';
  // 配置 Vue 插件
  Vue.use(ElementUI);

webpack基于图形化界面自动安装
1、运行 vue ui 命令,打开图形化界面
2、通过 Vue 项目管理器,进入具体的项目配置面板
3、点击 插件 -> 添加插件,进入插件查询面板
4、搜索 vue-cli-plugin-element 并安装
5、配置插件,实现按需导入,从而减少打包后项目的体积

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码上登堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值