Vue基础知识汇总(含webpack打包工具的使用)

基础知识一

框架和库的区别

  • 概念:小而巧的是库,大而全的是框架
  • 框架:是一套完整的解决方案,对项目的侵入性很大,项目若是须要更换框架,则须要从新架构整个项目
  • 库(插件):提供某一个小功能,对项目的侵入性较小,若是某个库没法完成某些需求,能够很容易的切换到其余库实现需求

MVC和MVVM思想

  • MVC 主要是后端的分层开发思想;把 一个完整的后端项目,分红了三个部分:javascript

    • Model:(数据层)主要负责 数据库的操做;
    • View:(视图层)全部前端页面,统称为 View 层
    • Controller:(业务逻辑层)主要处理对应的业务逻辑;(对于后台来讲,这是开发的重点)

  • MVVM是前端页面的分层开发思想,主要关注于 视图层 分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View, ViewModel
    • Model 是 页面中,须要用到的数据
    • View 是页面中的HTML结构;
    • ViewModel 是 一个 中间的调度者,提供了双向数据绑定的概念;
  • 为何有了MVC还要有MVVM
    • 由于 MVC是后端的开发思想,并无明肯定义前端的页面该如何开发;
    • MVVM 是前端的页面的开发思想,把每一个页面,分红了三个部分,同时 VM 做为 MVVM 的核心,提供了双向数据绑定的概念,前端程序员,不须要手动渲染页面了,并且,页面数据发送变化,也不须要程序员手动把 数据的变化同步到Model中;这全部的操做,都是 VM 自动完成的!
    • 有了 MVVM 的思想之后,前端只关心 页面交互逻辑,不关心页面如何渲染;

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

1. 注意:Vue中,不推荐程序员手动操做DOM元素;因此,在Vue项目中,没有极其变态的需求,通常不要引入 Jquery;
2. Vue代码解析执行的步骤:
   1. 当 VM 实例对象,被 建立完成以后,会当即解析 el 指定区域中的全部代码;
   2. 当 VM 在解析 el 区域中全部代码的时候,会把 data 中的数据,按需,填充到 页面指定的区域;
3. 注意:每当 vm 实例对象,监听到 data 中数据发生了变化,就会当即 从新解析 执行 el 区域内,全部的代码;
复制代码
<!-- 1.导入vue的包 -->
    <!-- 只要导入了vue的包,在window全局会挂载Vue成员(构造函数) --> <script src="./lib/vue-2.5.16.js"></script> </head>
<body>
    <!--2. 放一个id为app的div,未来new 出来的vue实例会控制这个div内部的代码 --> <!-- 注意:不能vm实例对象直接控制body或者是html--> <div id="app"> <h3>{{msg}}</h3> </div> <script> // 3new 一个Vue,建立Vue的实例对象 // new出来的vm实例对象就是mvvm中的 vm const vm=new Vue({ // 指定new 出来的vm实例要控制页面上的哪一个区域 el:'#app',//这个vm中指定的区域就是mvvm中view data:{//指定被控制的区域,要用到的数据 msg:'Hello Vue.js' }//这个data指向对象就是mvvm 中的model }); // function Person(obj){ // this.name=obj.name; // this.age=obj.age; // } // const p1=new Person({name:'zs',age:20}); </script> </body>
复制代码

Vue指令及插值表达式

定义:Vue中,经过一些特殊的用法,扩展了HTML的能力
复制代码
  • 未来 建立 Vue 实例的时候,Vue 会把 这些指令 都进行解析,从而,根据不一样的指令,执行不一样的操做、渲染不一样的结果;
Vue指令之 插值表达式 {{ }}
  1. 基本使用演示 在指定的位置动态插入内容,例如:
<p>{{msg}}</p>
复制代码
注意:指令是框架中提出的概念,扩展了html的能力,指令若是想要生效就必须被vm实例对象所解析
复制代码
  1. 在插值表达式中 使用简单的表达式,不能写语句
<div id="app">
        <h3>{{msg}}</h3>
        <h3>{{1+1}}</h3>
        <h3>{{boo ? '条件为真':'条件为假'}}</h3>
        <h3>{{msg.length}}</h3>
        <!--注意插值表达式只能在内容区域,不能在属性节点里面-->
        <h3>{{arr}}</h3>
       <!--不能写循环等语句-->
    </div>
    <script>
        const vm=new Vue({
            el:'#app',
            data: {
               msg:'Hello Vue.js',
               boo:false,
               arr:[1,2,3]
            },
        });
    </script>
复制代码
  1. 注意:插值表达式只能用在元素的内容区域;不能用在元素的属性节点中; 4.若是对于{{}}的这种形式不满意,能够经过下面的形式修改自定义的形式:
var vm = new Vue({
            delimiters:['$','#'],//把插值表达中的双花括号换成是指定的,可是通常不推荐
            el: '#app',
            data: {
                city: '北京',
                people: 2000
            }
        })
复制代码

5.对于自增和自减运算会出现异常,因此这里暂时不推荐在插值表达中使用自增自减元素。css

Vue指令之v-cloak
  1. 解决的问题
    • 插值表达式有闪烁的问题(v-cloak 指令来解决闪烁问题)
[v-cloak]{
            display: none;
        }
复制代码
  1. 应用场景
    • 当 网络比较卡的时候,咱们能够为 最外层的 元素,添加 v-cloak ,防止用户看到 插值表达式
  2. 原理
    • 经过vm建立完成以后,动态的移除v-cloak的属性,从而显示插值表达式的节点
Vue指令之v-text

1.基本使用 在元素的属性节点上,添加v-text 命令,例如:html

<p v-text="msg"></p>
复制代码

2.v-text中也可使用简单的语句 3.v-text与{{}}的区别前端

  • v-text会覆盖全部内容 {{}}不会覆盖
  • v-text不会出现闪烁问题,可是{{}}会出现闪烁问题

4.应用场景(v-text)vue

  • 向指定元素的内容区域中,渲染指定的文本
Vue指令之v-html

1.基本使用 在元素的属性节点上,添加v-text 命令,例如:java

<!-- 总结: vue 中的指令只有插值表达式是用在内容节点上的, 其余的全部指令都是用在属性节点的 -->
<p v-text="msg"></p>
复制代码

2.应用场景 当服务器返回的数据中,包含的html的标签,此时,这些标签只能在v-html来渲染node

Vue指令之 v-bind: 属性绑定(自定义属性和固有属性)
添加在元素节点身上的属性均可以经过v-bind进行绑定(id width src)等
复制代码

1.基本使用react

  • v-bind:是为html属性节点动态绑定数据的,例如:
<div id="app">
        <!-- v-bind:指令表示属性绑定, 能够在v-bind中写一些简单的表达式 从此在开发中很是经常使用 v-bind:指令能够简写为英文的:表明的是属性绑定 -->
        <button :title="titleStr">按钮</button>
        <img :src="boo ? img:img1" alt="">
        <!-- <img v-bind:src="img1" alt=""> -->
    </div>
    <script> // 当vm实例被建立完毕后会当即解析执行el区域内全部vue的指令 // 并且只要data数据中发生了变化,就会当即从新解析数据 const vm=new Vue({ el:'#app', data:{ titleStr:'这是title属性值', boo:false, img:'https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=2391791031,3623366227&fm=26&gp=0.jpg' ,img1:'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=486958716,243120904&fm=26&gp=0.jpg' } }) </script>
复制代码

2.应用场景webpack

  • 若是元素的属性值,须要动态地进行绑定,则须要使用v-bind: 指令
Vue指令之v-on:事件绑定
  1. 基本使用: v-on: 的做用,是为 HTML 元素,绑定 事件处理函数,例如:
<input type="button" value="按钮" v-on:click="事件处理函数名" />
复制代码
  1. 绑定事件处理函数并传参:
<input type="button" value="按钮" v-on:click="show(123)" />
复制代码
关于参数问题:
1. 有传递使用传递的参数
2. 没有声明(),第一个形参就是事件对象object MouseEvent
3. 有声明(),尚未传递实参,形参就是undefined
   methods: {
            // 成员方法
                exp(id){
                    console.log('商品被删除了'+id);
                }
                // 不传递实参的状况下是undefined
                // 不加括号[object MouseEvent]
            },

复制代码
  1. 简写形式: v-on: 指令能够简写成 @,例如,能够简写成以下格式:
<input type="button" value="按钮" @click="事件处理函数名" />
复制代码
Vue指令之v-modle实现双向绑定

1.基本使用:ios

  • 能够把页面上数据的变化,自动同步更新到 VM 实例的 data 中。例如:
<input type="text" v-model="msg"/>
复制代码

2.和v-bind的区别

  • v-bind: 只能实现单向的数据同步 data ---> 页面;
  • v-model 能够实现双向的数据同步 data <--> 页面;
  • 在写法上v-bind能够简写为:的形式.v-model没有简写方式
  • v-model ="msg",:v-bind:src="mySrc",他们里面的属性值都须要在data中设置,哪怕没有值也须要设置为空字符串。 3.注意:
  • v-model只能和表单元素配合使用,例如input select textarea等
  • v-model是Vue中惟一支持双向数据绑定的指令.

4.v-model简易版原理整理 v-model的原理就给input输入框中定义oninput事件,在该事件中把用户输入的信息都给随时得到到,并对data成员进行赋值

data成员变化了,页面上用到的地方就从新渲染,达成简易双向绑定的效果 代码以下:

<div id="app">
        <p>{{city}}</p>
        <!-- 这里的$event就表明的是event -->
        <input type="text" @input="city=$event.target.value" :value="city">
        <input type="text" @input="feel" :value="city">
    </div>
    <script src="./vue.js"></script>
    <script>
    var vm=new Vue({
        el:'#app',
        data:{
            city:'北京'
        },
        methods: {
            feel(evt){
            //    console.log(evt);
            // console.log(evt)  // InputEvent对象
        // evt.target:表明触发当前事件的html元素dom对象,具体是input框对象
        // evt.target.value: 随时感知输入框输入的信息

        // 把随时输入的信息赋予给city,这样city变化,因为“从新渲染”,页面上用到的地方就更新了
        // 就达成v-model双向绑定的效果了  
            this.city=evt.target.value;
            }
        },
    })
    </script>
复制代码

5.应用场景: 简易计算器的实现:

<body>
    <div id="app">
        <!-- 第一个运算的数值 -->
        <input type="text" v-model="n1">
        <select v-model="opt">
            <option value="+">+</option><br>
            <option value="-">-</option><br>
            <option value="*">*</option><br>
            <option value="/">/</option><br>
        </select>
        <!-- 第二个元素的数值 -->
        <input type="text" v-model="n2">
        <!-- 注意这里不要写错 -->
        <button @click="calc">=</button>
        <!-- 运算的结果 -->
        <input type="text" readonly :value="result">
    </div>
    <script> const vm=new Vue({ el:'#app', data:{ n1:0, n2:0, opt:'+', result:0 }, methods: { calc(){ switch(this.opt){ case '+': this.result= parseFloat(this.n1)+parseFloat(this.n2); break; case '-': this.result= parseFloat(this.n1)-parseFloat(this.n2); break; case '*': this.result= parseFloat(this.n1)*parseFloat(this.n2); break; case '/': this.result= parseFloat(this.n1)/parseFloat(this.n2); break; } } }, }) </script>
</body>
复制代码
this 操控data

根据业务须要,事件在执行过程当中须要对Vue实例的data数据进行操做,经过this关键字实现,

this表明Vue实例对象,而且针对data或methods成员均可以直接进行调用

在Vue中使用class样式

1.类名数组

  • 经过 v-bind: 为元素的 class 绑定具体的类名:
<p :class="['thin', 'red', 'big']">哈哈哈</p>
复制代码

2.类名数组中使用三元表达式,按需为元素添加某些类名

<button @click="getInfo()" >获取数据</button>

<script>
  var vm = new Vue({
    el:'#app',
    data:{
      address:'铁岭'
    },
    methods:{
      getInfo:function(){
        // 经过 this关键字 得到 data区域的数据信息
        console.log(this.address+'是一个大城市');
      }
    }
  })
</script>
复制代码
<p :class="['thin', flag ? 'red' : '']">哈哈哈</p>
复制代码

3.应用场景

  • 网页开关灯
<div id="app" :class="[flag ? 'light':'dark']">
        <button @click="flag=!flag">切换</button>
        <h1>{{msg}}大渣好,我系咕天乐,我系渣渣辉,贪挽难约,介系一个你没有挽过的船新版本,挤需体验3番钟,里就会干我同样,挨上节款游戏</h1>
        <img :src="flag ? img1:img2" alt="">
    </div>
    <script>
        const vm=new Vue({
            el:'#app',
            data:{
                //false是黑夜,true是白天
                flag:false,
                img1:'./images/6.jpg',
                img2:'./images/段段.jpg'
            }
        })
    </script>
复制代码
在Vue中使用style样式

style属性也比较特殊,其能够给标签设置许多css样式,在vue中能够作以下应用

- 对象语法
      <div :style="{color: 'red', 'font-size': '20px', fontWeight:'bold' }"></div>
- 数组语法
      <div :style="[{color: 'red'}, {'font-size': '20px', fontWeight:'bold' }]"></div>
复制代码

在一个数组元素中能够绑定多个或一个样式成员 有的样式属性名称是经过"-"中横线链接的,这在javascript的命名规则中不容许的,例如font-size、font-weight,在处理时有两种方式

  1. 引号限定 如 'font-size'
  2. 中横线去除,后边首字母大写 如 fontWeight

以上对象或数组绑定class语法均渲染为:

<div style="color:red; font-size:20px; font-weight:bold"></div>

复制代码

经过 数组 或 对象 对 class/style 进行绑定的好处是,属性值能够嵌入编程内容,实现精细化控制

Vue指令之v-for和:key属性

1.基本用法:

  • 普通数组 (通常般)
<li v-for="(item,i) in list1">{{item}}---索引{{i}}</li>
复制代码
  • 对象数组(用的最多)
<li v-for="(item,i) in list2">{{item.id}}---{{item.name}}---索引值{{i}}</li>
复制代码
  • 迭代对象中的属性
  • 迭代数字 (这两种方法平时不怎么用,因此这里不详细介绍了)

2.:key的用法

<li v-for="item in list2" :key="item.id">{{item.id}}---{{item.name}}---索引值{{i}}</li>
复制代码
注意:从此只要用到了id值,就必定要为循环的每一项,添加:key属性绑定,并且key的值最好绑定到id值上,key的值必定要惟一,单独的使用索引值也是不能够的,由于这个key值是用来标识数据惟一性的,经过key绑定的数据项和数据状态(好比复选框的选中伪选中关系)之间的关系
复制代码
Vue中v-if和v-show指令
  • v-if 和 v-show 的做用,都是切换界面上元素的显示或隐藏的;
<div id="app">
        <button @click="flag=!flag">Toggle</button>{{flag}}
        <!-- v-if是经过动态建立或者移除元素实现动态切换 -->
        <h3 v-if="flag">奔跑的五花肉</h3>
        <hr>
        <!-- v-show是经过控制元素的display:none样式实现切换 -->
        <h3 v-show="flag">2432432</h3>
    </div>
复制代码
通常来讲,v-if 有更高的切换消耗 而  v-show 有更高的初始渲染消耗。

所以,若是须要频繁切换 v-show 较好,若是在运行时条件不大可能改变 v-if 较好。

复制代码

修饰符

事件修饰符(用来修饰事件的,若是点击事件)

.prevent 阻止默认行为(使用最频繁)

<a href="http://www.baidu.com" @click.prevent="show">百度</a>
复制代码

.once 只触发1次(几乎不经常使用)

<button @click.once="btnHandler">按钮</button>
复制代码

.stop阻止冒泡

<button @click.stop="btnHandler">按钮</button>
复制代码

.self只有在当前元素上触发事件的时候,才会调用处理函数

<div class="inner" @click.self="innerHandler"></div>
复制代码
按键修饰符

按键修饰符是配合文本框的使用的 .enter

<input type="text" v-model="password" @keyup.enter="login"><br>

复制代码

.tab

<input type="text" v-model="password" @keyup.tab="login"><br>

复制代码

.esc

<input type="text" v-model="password" @keyup.esc="login"><br>

复制代码

基础知识二

Vue过滤器

"2018-01-25T02:10:02.945Z"    =>   2018-01-25
复制代码

概念:过滤器的本质就是一些函数,可被用做一些常见的文本格式化

  • 过滤器只能用在两个地方,插值表达式和v-bind表达式中
<td :title="item.ctime |dateFormate">{{item.ctime | dateFormate}}</td>
复制代码
  • 过滤器应该被添加在javascript表达式的尾部,由 管道 符指示

全局过滤器

1.使用全局过滤器的语法

<span>{{ dt | 过滤器的名称 }}</span>
|的做用就是调用一个过滤器
复制代码

2.定义全局过滤器的语法

  • Vue.filter('过滤器的名称', function(originVal){ /* 对数据进行处理的过程,在这个 function 中,最后必须 return 一个处理的结果 */ })
注意:全局过滤器必须定义在new Vue()以前
复制代码

3.使用过滤器的注意事项

  • 若是想拿管道符前面的值,经过 function 的第一个形参来拿
  • 过滤器中,必定要返回一个处理的结果,不然就是一个无效的过滤器
  • 在调用过滤器的时候,直接经过 () 调用就能传参; 从过滤器处理函数的第二个形参开始接收传递过来的参数
  • 能够 屡次 使用 | 管道符 一次调用多个过滤器
<div id="app">
        <!-- 在插值表达式中可使用|管道符来调用指定的过滤器 -->
        <!-- 若是调用过滤器了,则在这个内容区域显示的内容是过滤器方法最终返回的处理结果 -->
        <!-- 过滤器只是对原有的数据作了一层包装,并无修改原来的值 -->
        <h3>{{dt | dateFormate}}</h3>
        <p>{{dt}}</p>
    </div>
    <script>
        // 经过Vue.filter定义一个全局过滤器
        // 注意,调用过滤器的时候,管道符前面的值,必须经过function的第一个参数接收
        // Vue.filter('过滤器的名称',function(originVal){//过滤器的处理函数

        // })
        Vue.filter('dateFormate',function(originVal){
            //最终必定要返回一个处理结果
            // return originVal+'-------'
            const dt=new Date(originVal);
            const y=dt.getFullYear();
            const m=(dt.getMonth()+1+'').padStart(2,'0');
            const d= (dt.getDate()+'').padStart(2,'0');
            const hh= (dt.getHours()+'').padStart(2,'0');
            const mm=(dt.getMinutes()+'').padStart(2,'0');
            const ss= (dt.getSeconds()+'').padStart(2,'0');

            const dtstr=`${y}-${m}-${d} ${hh}:${mm}:${ss}`;

            return dtstr;
        });
        const vm=new Vue({
            el:'#app',
            data:{
                dt:'2018-01-25T02:10:02.945Z'
            },
            methods: {
                
            },
        })
    </script>
复制代码

私有过滤器

const vm=new Vue({
            el:'#app',
            data:{
                dt:'2018-01-25T02:10:02.945Z'
            },
            methods: {
               
               
            },
            // 注意是跟methods同级
             // 注意:私有的过滤器带s,全局过滤器不带过滤器
             // 私有过滤器的名称:function (){//私有过滤器的处理函数}
            //  过滤器是按照就近原则进行调用的,先调用私有的,若是私有过滤器先看私有过滤器,没有再看全局过滤器
             filters:{
                //  es3写法
                    // dateFormate:function(originVal){
                    //     return originVal+'-----'
                    // }
                // es6写法
                    dateFormate(originVal){
                        return originVal+'-----'
                    }
                }
        })
复制代码
过滤器是按照就近原则进行调用的,先调用私有的,若是私有过滤器先看私有过滤器,没有再看全局过滤器
复制代码

带参数的过滤器

有的时候,过滤器主体业务逻辑不变化的状况下,可能结果的形式根据业务要求有所调整,为了加强灵活度,能够经过传递参数实现。

Vue实例.$mount()动态挂载实例

语法:Vue.$mount("选择器 - 指定要控制的区域")

const vm=new Vue({
            data:{
                msg:'Hello'
            }
        });

        //mount是挂载的意思,表示 手动指定当前的vm实例要控制的区域
        vm.$mount('#app');
复制代码

template属性指定模块

语法:template:'<h6>{{msg}}</h6>'

const vm=new Vue({
            el:'#app',
            data:{
                msg:'Hello'
            },
            methods: {},
            filters:{},
            // 指定当前vm要渲染的模版
            // 结论:若是同时指定了el和template,那么template会把el区域替换掉
            template:'<h6>{{msg}}</h6>'
        })
复制代码

Vue的生命周期

生命周期

概念 : 实例的生命周期,就是一个阶段,从建立到运行,再到销毁的阶段;

生命周期函数

在实例的生命周期中,在特定阶段执行的一些特定的事件,这些特定的事件叫作生命周期函数

  • 生命周期函数=生命周期钩子=声明周期事件
主要的生命周期函数分类
  • 建立期间的生命周期函数(特色:每一个实例一生只执行一次)
    • beforeCreate:建立以前,此时data和methods方法还没有初始化,还不能访问里面的数据
    • created:(第一个重要的函数,此时data和methods已经建立好了,里面的数据还有方法均可以被访问了)
    • beforeMounted:挂载模版以前,此时页面尚未被渲染出来
    • mounted:(第二个重要的函数,此时,页面刚被渲染出来,,若是要操做DOM元素,最好在这个阶段)
  • 运行期间的生命周期函数(特色,按需被调用,至少0次,最多N次)
    • beforeUpdate :数据是最新的,可是页面仍是旧的页面
    • updated 页面和数据都是最新的
  • 销毁期间的声明周期函数(特色:每一个实例一生只执行一次)
  • beforeDestroy:销毁以前,实例还能够正常使用
  • destroyed :销毁以后,实例已经不存在,没法工做了

axios的使用

<script>
    // 经过这个属性,全局设置 请求的 根路径
    axios.defaults.baseURL = 'http://www.liulongbin.top:3005'
    // 未来项目中都这么搞
    Vue.prototype.$http = axios

    // 建立 Vue 实例,获得 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {
        async getInfo() {
          const { data: res } = await this.$http.get('/api/get', { params: { name: 'zs', age: 22 } })
          console.log(res)
        },
        async postInfo() {
          const { data: res } = await this.$http.post('/api/post', { name: 'zs', age: 22 })
          console.log(res)
        }
      }
    });
  </script>

复制代码
注意:axios这个库能够在任意的请求中使用,他们发送get和post请求时的参数是不相同的,get请求参数是params而那个post请求,请求参数是data,可是这里太过麻烦,就用对象结构赋值的方式将代码进行解构
复制代码
axios的缺点
  • 只支持 get 和 post 请求,没法发起 JSONP 请求;
  • 若是涉及到 JSONP 请求,可让后端启用 cors 跨域资源共享便可;

在Vue中,还可使用 vue-resource 发起数据请求

  • vue-resource 支持 get, post, jsonp请求【可是,Vue官方不推荐使用这个包了!】

基础知识三

Vue中的动画

Vue中动画的基本介绍

使用动画的缘由
  • 动画可以增长页面的趣味性,目的是为了让用户更好的理解页面的功能
注意:Vue中的动画,都是简单的动画过渡,并不会有CSS3那么炫酷
复制代码
动画简单介绍

1.每一个动画都是由两部分组成的:

- 入场动画:从不可见(flag = false) -> 可见(flag = true)
- 出场动画:可见(flag = true) -> 不可见(flag = false)
复制代码
  1. 入场时候,Vue把这个动画,分红了两个时间点和一个时间段:
    • v-enter:入场前的样式
    • v-enter-to:入场完成之后的样式
    • v-enter-active:入场的时间段
  2. 离场时候,Vue把动画,分红了两个时间点和一个时间段:
    • v-leave:离场以前的样式
    • v-leave-to:离场完成之后的样式
    • v-leave-active:离场的时间段

动画图示:

总结:带active的都是时间段的效果,
     带to的都是完成以后的状态,
     什么也不带的都是开始时的状态
    
也就是说动画都是从哪来,从哪去

复制代码
使用过渡类名
  1. 把须要添加动画的元素,使用v-if或v-show进行控制
  2. 把须要添加动画的元素,使用Vue提供的元素 包裹起来
  3. 添加两组类:
<style> /* 定义元素入场之间和离场以后的位置 */ /* 注意:他在入场以前并非标准里的位置 */ .v-enter, .v-leave-to { transform: translateX(150px); opacity: 0; } /* 定义元素,入场阶段,和离场阶段的过渡效果 */ .v-enter-active, .v-leave-active { transition: all 0.8s; } /* 动画完成以后,默认的位置就是标准流中的效果 */ /* 定义元素在标准流中的效果, 这个标准流的效果就是入场完成以后,移入离场开始以前,元素的效果*/ h3 { transform: translateX(50px); opacity: 0.5; } /* 经过类名,能够设置页面上的多组动画效果 */ .test-enter,.test-leave-to{ opacity: 0; transform: translateY(200px); } .test-enter-active, .test-leave-active{ transition: all 0.8s; } </style>
复制代码

此时transition身上的name属性也要改为对应的属性值

<div id="app">
        <button @click="flag=!flag">Toggle</button>
        <!-- 1.使用vue框架提供的transition标签,把须要添加过渡的效果包裹起来 -->
        <transition name="">
            <h3 v-if="flag">函数哈哈胡莎莎</h3>
        </transition>
        <hr>
        <button @click="flag2=!flag2">Toggle</button>
      <transition name="test">
            <h6 v-if="flag2">这是第二个元素</h6>
      </transition>
    </div>
复制代码
注意:v-if和v-show在前面讲过是控制元素的显示和隐藏,具体的操做能够再回顾一下上面的笔记.
复制代码
使用第三方的css动画库
  1. 把须要添加动画的元素,使用v-if或v-show进行控制
  2. 把须要添加动画的元素,使用Vue提供的元素 包裹起来
  3. 为 添加两个属性类enter-active-class, leave-active-class
  4. 把须要添加动画的元素,添加一个 class="animated"
<div id="app">
        <button @click="flag=!flag">Toggle</button>
        <!-- 指定入场的类名 -->
        <transition enter-active-class="bounceInDown" leave-active-class="bounceOutDown">
            <h3 v-if="flag" class="animated"> 哇哈哈哈哈哈哈</h3>
        </transition>
    </div>
复制代码
v-for的列表过渡
  1. 把v-for循环渲染的元素,添加 :key 属性[注意:若是要为列表项添加动画效果,必定的指定key,而且key的值不能是索引]
  2. 在 v-for循环渲染的元素外层,包裹 标签
  3. 添加两组类便可:
<!-- transition-group这个标签要放在ul里面,而且这个标签会自动的渲染为span -->
            <!-- 可是这里也能够强制的将这个标签渲染为ul,这时,外面的ul属性也不须要设置了 -->
            <transition-group tag="ul">
                <li v-for="item in list" :key="item.id">
                    {{item.id}}---{{item.name}}
                </li>
            </transition-group>
复制代码
列表的排序过渡

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

  • v-move 和 v-leave-active 结合使用,可以让列表的过渡更加平缓柔和:
<style>
   /* 为即将被删除的元素,添加样式,让他脱离标准流 */
        .v-leave-active{
            position: absolute;
            width: 100%;
        }
        /* 经过.v-move这个类,可让后续的元素,经过过渡,渐渐的顶上去 */
        /* 若是不加这个类的话,下面的元素会一下就顶上去,也就没有了过渡的效果 */
        .v-move{
            transition: all 0.8s;
        }
    </style>
复制代码

Webpack

什么是webpack?

  • 什么是webpack:webpack 是前端项目的构建工具;前端的项目,都是基于 webpack 进行 构建和运行的;
  • 为何要使用webpack:
    1. 若是项目使用 webpack 进行构建,咱们能够书写高级的ES代码,且不用考虑兼容性;
    2. webpack 可以优化项目的性能,好比合并、压缩文件等;
    3. 基于webpack,程序员能够把 本身的开发重心,放到功能上;
  • 什么项目适合使用webpack:
    • webpack 很是适合与 单页面应用程序(SinglePageApplication) 结合使用;
      • vue, react, angular 只要用前端三大框架开发项目,必然会使用webpack工具;
    • 不太适合与多页面的普通网站结合使用;
  • 根据webpack官网的图片介绍webpack打包的过程
  • webpack分不少版本 1.x 2.x 3.x 4.x

ES6导入导出语法

因为下面的笔记,在配置的时候可能会遇到ES6中导入导出的语法,因此这里提早在笔记中记录一下。

在webpack中一切皆模块,这里主要是ES6中模块化的导入和导出。

在webpack中,每一个js文件都须要独立的模块,每一个模块都有独立的做用域,其余模块默认没法直接访问当前模块中定义的成员。

默认导入导出方式

1.默认导入

默认导入的语法可使用任何合法的名称来进行接收
import 接收名称 from '模块名称'
复制代码

2.默认导出语法:

export default {

    a:a
}
复制代码
按需导入和导出
  1. 按需导入语法: import { 成员名称 } from '模块名称'
  2. 按需导出语法: export var a = 10

在项目中安装和配置

webpack 是前端的一个工具,这个工具,能够从NPM官网上下载到本地使用;

  1. 新建一个项目的空白目录,并在在终端中,cd到项目的根目录,执行npm init -y 初始化项目
  2. 装包:运行 npm i webpack webpack-cli -D 安装项目构建所须要的 webpack
  3. 打开 package.json文件,在 scripts 节点中,新增一个 dev 的节点:
  4. 在项目根目录中,新建一个 webpack.config.js 配置文件,内容以下
{
  "name": "code2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"webpack" 
  },

复制代码
  1. 在项目根目录中,新增一个 src 目录,而且,在 src 目录中,新建一个 index.js 文件,做为 webpack 构建的入口;会把打包好的文件输出到 dist -> main.js
  2. 在终端中,直接运行 npm run dev 启动webpack进行项目构建;

实现webpack的实时打包构建

  1. 借助于 webpack-dev-sever 这个工具,可以实现 webpack 的实时打包构建;
  2. 运行npm i webpack-dev-server -D 安装包
  3. 打开package.json文件,把 scripts 节点下的 dev 脚本,修改成以下配置:
"scripts": {
           "test": "echo \"Error: no test specified\" && exit 1",
           "dev": "webpack-dev-server"
         },
复制代码
  1. 修改 index.html 文件中的 script 的 src, 让 src 指向 内存中根目录下的 /main.js
<script src="/main.js"></script>
复制代码

使用html-webpack-plugin插件配置启动页面

  1. 装包npm i html-webpack-plugin -D
  2. 在 webpack.config.js中,导入 插件:
// 导入 html-webpack-plugin,从而帮咱们自动把 打包好的 main.js 注入到 index.html 页面中
       // 同时,html-webpack-plugin 能够把 磁盘上的 index.html 页面,复制一份并托管到 内存中;
       const HtmlPlugin = require('html-webpack-plugin')
       const htmlPlugin = new HtmlPlugin({
         // 传递一个配置对象
         template: './src/index.html', // 指定路径,表示 要根据哪一个物理磁盘上的页面,生成内存中的页面
         filename: 'index.html' // 指定,内存中生成的页面的名称
       })
复制代码
  1. 把 建立好的 htmlPlugin 对象,挂载到 plugins数组中:
// webpack 这个构建工具,是基于 Node.js 开发出来的一个前端工具
       module.exports = {
         mode: 'development', // 当前处于开发模式
         plugins: [htmlPlugin] // 插件数组
       }
复制代码

实现自动打开浏览器、热更新和配置浏览器的默认端口号

  • --open 自动打开浏览器
  • --host 配置IP地址
  • --port 配置 端口号
  • --hot 热更新;最新的代码,以打补丁的形式,替换到页面上,加快编译的速度;

webpack打包非js文件

webpack打包css文件

因为webpack只能打包js文件,因此对于非js文件就须要单独进行处理

使用webpack打包css文件

  1. 运行 npm i style-loader css-loader -D
  2. 打开 webpack.config.js 配置文件,在 module -> rules 数组中,新增处理 css 样式表的loader规则:
module: { // 全部 非.js 结尾的第三方文件类型,均可以在 module 节点中进行配置
           rules: [ // rules 是匹配规则,若是 webpack 在打包项目的时候,发现,某些 文件的后缀名是 非 .js 结尾的
             // webpack 默认处理不了,此时,webpack 查找 配置文件中的 module -> rules 规则数组;
             { test: /\.css$/, use: ['style-loader', 'css-loader'] }
           ]
         }
复制代码
注意:因为使用非js文件打包,都须要对他进行loader的出来,可是这里css-loader也有他本身的调用顺序,这里这个loader的调用时逆向的,先调用css-loader,而后再调用style-loader
复制代码

使用webpack打包less文件

  1. 运行 npm i less-loader less -D
  2. 在 webpack 的配置文件中,新增一个 rules 规则来 处理 less 文件:
{ test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }
复制代码
注意:只要是样式表,在他的loader配置中都须要加上style-loader和css-loader这两个选项。
复制代码

使用webpack处理css中的路径

  1. 运行 npm i url-loader file-loader -D
  2. 在 webpack 的配置文件中,新增一个 rules 规则来 处理 图片 文件:
{ test: /\.jpg|png|gif|bmp$/, use: 'url-loader' }
复制代码

webpack中使用bootstrap

  1. 运行 npm i bootstrap 对bootstrap装包
  2. 在webpack中使用bootstrap自己没有问题,可是因为boostrap自己引入了其余的字体的样式表,这里又只能打包的是js文件,因此这里还须要字体样式表的loader
{ test: /\.eot|woff|woff2|ttf|svg$/, use: 'url-loader' }
复制代码

默认状况下,若是导入的模块是路径,webpack会优先去node_modules目录下,查找指定的路径是否存在

注意:这里打包字体文件和loader和打包处理图片的loader都是url-loader
复制代码

使用babel处理高级JS语法

1.因为webpack默认只能打包处理一部分高级的js的语法,若是某些js语法,过于高级,则webpack也是处理不了的,此时只能借助于babel这个插件,来打包处理高级的js语法 2.运行两套命令,去安装相关的 loader:

- 运行 npm i babel-core babel-loader babel-plugin-transform-runtime -D
- 运行 npm i babel-preset-env babel-preset-stage-0 -D
复制代码
  1. 添加 babel-loader 配置项:
// 注意:在配置 babel-loader 的时候,必定要添加 exclude 排除项,把 node_modules 目录排除
       // 这样,只让 babel-loader 转换 程序员 本身手写的 JS 代码;
       // 好处:1. 可以提升编译的转换效率; 2. 可以防止没必要要的报错!
       { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
复制代码
  1. 在项目根目录中,添加 .babelrc 配置文件:
{
         "presets": ["env", "stage-0"],
         "plugins": ["transform-runtime"]
       }

复制代码

基础知识四

在 webpack 中安装和配置 vue

  1. 运行 npm i vue -S 把 vue 安装到项目依赖
  2. 在 index.js 中使用 import 导入 vue 模块:
import Vue from 'vue'
复制代码
  1. 在 index.html 中建立未来要被 vm 实例控制的 div:
<!-- 未来,这个 div 就是 Vue实例 要控制的区域 -->
       <div id="app"></div>
复制代码
  1. 在 index.js 中建立 vm 实例,并使用 el 指定要控制的区域,使用 data 指定要渲染的数据:
const vm = new Vue({
         el: '#app', // 要控制的区域
         data: {
           msg: 'ok' // 要渲染的数据
         }
       })
复制代码

为何在基于 webpack 的 vue项目中, 按照如上操做会报错呢

  1. 由于使用 import 导入的 vue 模块,导入的并非功能最全的 vue 包;而是删减版的;
  2. 删减版的 vue 包中功能不多,目的是为了减少vue 包的体积,由于文件越小,网络请求越快!
  3. 如何让 import 导入最全的 vue 包呢?
- 把 import Vue from 'vue' 改写为 import Vue from 'vue/dist/vue.js'
复制代码
  1. 注意:在学习阶段,能够暂时 import 最全的 vue 包;等开发项目的时候,必定要使用 删减版的 包;

定义Vue组件

模块化和组件化的概念解读

  1. 什么是模块化:是从代码的角度分析问题;把可复用的代码,抽离为单独的模块;
    • 模块化的好处:
      • 提供模块做用域的概念,防止全局变量污染;
      • 提升了代码的复用率,方便了程序员之间 共享代码;
  2. 什么是组件化:组件化是从页面UI的角度进行分析问题的;把页面中可复用的UI结构,抽离为单独的组件;
    • 组件化的好处:
      • 方便了UI结构的重用;
      • 随着项目开发的深刻,手中可用的组件会愈来愈多;
      • 能够直接使用第三方封装好的组件库;
      • 组件化可以让程序员更专一于本身的业务逻辑;

定义全局组件

1.定义组件的语法

  • Vue.component('组件的名称', { 组件的配置对象 });

  • 在组件的配置对象中:可使用 template 属性指定当前组件要渲染的模板结构;

Vue.component('my-test',{
    template:`<div>这是我定义的第一个Vue组件</div>`
});
注意:这里的组件名称最好都写成是小写的,而且中间最好用-链接一下
复制代码
  • 在组件的配置对象中:可使用 template 属性指定当前组件要渲染的模板结构;

2.使用组件的语法(全局组件)

  • 把 组件的名称, 以标签的形式,引入到页面上就行; 注意:

  • 从更抽象的角度来讲,每一个组件,就至关因而一个自定义的元素;

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

Vue.component('my-test',{
    template:`<div> <div>这是我定义的第一个Vue组件</div> <div>这是我定义的第一个Vue组件</div> </div>`
});
复制代码

3.使用组件的语法(私有组件)

注意:定义私有组件,只能在定义区域内使用,超出定制区域内使用无效,会报错误

const vm = new Vue({
    el: '#app',
    data: {
        msg: 'Hello World!'
    },
    components: {
        //使用compoents属性定义的组件,叫作是私有组件 
        // '组件名称':{/组件的配置对象/}
        'my-test2': {
            template: `<div>这是私有组件</div>`
        }
    }
})
复制代码

组件中定义data数据、methods方法以及生命周期函数

组件中定义data数据
Vue.component('my-test', {
    template: `<div> <div>这是我定义的第一个Vue组件{{d1}}</div> <div>这是我定义的第一个Vue组件</div> </div>`,
    // 注意Vue规定,组件中的data必须是function函数,并且必须return一个对象
   data(){
    // return 当前实例对象
       return {
           d1:'111'
       }
   }
});
复制代码

区分vm实例中定义data数据

//在vm实例中,data既能够是对象也能够方法,可是在组件中只能是方法
const vm = new Vue({
    el: '#app',
    // data: {
    //     msg: 'Hello World!'
    // },
    data() {
        return {
            msg: 'Hello World!'
        }
    },
    components: {
        //使用compoents属性定义的组件,叫作是私有组件 
        // '组件名称':{/组件的配置对象/}
        'my-test2': {
            template: `<div>这是私有组件</div>`
        }
    }
})
复制代码
组件中定义本身的methods,fifters以及生命周期函数
Vue.component('my-test', {
    template: `<div> <div @click="show">这是我定义的第一个Vue组件{{d1}}</div> <div>这是我定义的第一个Vue组件</div> </div>`,
    // 注意Vue规定,组件中的data必须是function函数,并且必须return一个对象
   data(){
    // return 当前实例对象
       return {
           d1:'111'
       }
   },
   //组件中也能够有本身的私有方法
   methods: {
       show(){
           console.log('调用了自定义组件中的show方法')
       }
   },
    //组件中也能有本身的私有过滤器
    filters:{
        testFilter(originval){
            return originval+'~~~'
        }
    } ,
    // 组件也能够有本身的声明周期函数
    created() {
        console.log('调用了created函数')
;    },
复制代码
组件和实例的区别
  1. 组件中的 data 必须是一个 function 并 return 一个 字面量对象;在 Vue 实例中,实例的 data 既能够是 对象,能够是 方法;

  2. 组件中,直接经过 template 属性来指定组件的UI结构;在 Vue 实例中,经过 el 属性来指定实例控制的区域;可是实例也可使用 template;

  3. 组件和实例,都有本身的生命周期函数,私有的过滤器,methods 处理函数;

为何组件中的 data 属性必须定义为一个方法并返回一个对象

主要是内存中存储的地址不同,具体操做能够看下图的指示:

.vue单文件组件

  • 为何要把组件,单独的定义到 .vue 文件中?

    • 以前建立组件太麻烦,没有智能提示和代码高亮;
    • 以前定义组件,和其它JS代码逻辑掺杂在一起,代码不易维护,没有把组件化的优点发挥到极致!
  • 每一个 .vue 文件,都是一个 vue 组件(叫作 单文件组件),它由三部分组成:

    1. template 结构
    2. script 行为
    3. style 样式
<template>
    <div>
        <!--注意单文件中的template节点只能有惟一的父元素进行包裹  -->
        <h3>这是使用.vue文件定义单文件组件---{{msg}}</h3>
    </div>
</template>
<script>
// 行为中固定写法
// 当前组件中私有的data数据
export default {
    data(){
        return {
            msg:'hello .vue文件'
        }
    },
    methods:{},
    filters:{},
    created(){}
}
</script>
<style >
h3{
    color: red;
}
</style>
复制代码

在webpack中配置.vue组件页面的解析

// 导入单文件组件
import Home from './components/HOME.vue';
//把单文件组件,以Vue.compondent注册为全局组件
Vue.component('my-home',Home);
复制代码

从上述代码中能够看出,当前导入的是.vue文件,不是以js为后缀名的文件,同时也不是咱们以前处理的文件类型,因此这里在浏览器运行就会报出一个没有loader的错误.

  1. 运行npm i vue-loader vue-template-compiler -D
  2. 添加rules匹配规则:
{ test: /\.vue$/, use: 'vue-loader' }
复制代码
  1. 在webpack.config.js中导入并配置插件:
// 导入插件
       const VueLoaderPlugin = require('vue-loader/lib/plugin')
       // new 一个插件的实例对象
       const vuePlugin = new VueLoaderPlugin()
       
       // 把 new 出来的插件实例对象,挂载到 `plugins` 节点中:
       plugins: [...其它插件, vuePlugin]
复制代码

导入并使用 .vue 组件的两种方式

全局注册 .vue 文件:

  • 在 index.js 中导入 .vue 组件
  • 使用 Vue.component() 把导入的 .vue 组件,注册为全局组件
// 导入单文件组件
import Home from './components/HOME.vue';
//把单文件组件,以Vue.compondent注册为全局组件
Vue.component('my-home',Home);

const vm=new Vue({
    el:'#app',
    data:{

    }
})
复制代码

2.私有注册 .vue 文件:

  • 定义两个独立的组件 Home.vue 和 Son.vue
  • 在 Home.vue 组件中,导入 Son.vue 文件,并使用 Home.vue 组件的 components 属性,把 Son.vue 注册为本身的私有子组件
//导入son组件
import Son from './Son.vue';

// 行为中固定写法
// 当前组件中私有的data数据
export default {
    data(){
        return {
            msg:'hello .vue文件'
        }
    },
    // 在.vue文件中,能够经过components属性,将另一个.vue组件,定义为本身的私有组件
    
    components:{
        'my-son':Son,
    }
}
复制代码

组件中的样式问题

因为咱们指望在组件中的样式只在当前组件中生效,可是咱们经过运行能够发现,子组件在父组件中使用,他也被父组件的样式影响,这个是由于默认状况下,组件中定义的样式是全局组件,因此可使用下面的这种方法:

<style  scoped>

/* 咱们指望在组件中的样式只在当前组件中生效 */
/* 因此从此,咱们都须要给组件的style添加scoped,防止样式冲突 */

  h3 {
    color: red;
  }

</style>>
复制代码

若是咱们但愿使用标签嵌套的方式,也就是less的文件样式,就须要添加一个lang="less"属性,

<style lang="less" scoped>
/* 咱们指望在组件中的样式只在当前组件中生效 */
/* 因此从此,咱们都须要给组件的style添加scoped,防止样式冲突 */
.home-box {
    border: 1px solid #000;
  h3 {
    color: red;
  }
}
</style>>

复制代码

组件之间的数据通讯

父组件向子组件传递普通数据

1.在父组件中,以标签形式使用子组件的时候,能够经过属性绑定,为子组件传递数据:

<my-son :pmsg1="parentMsg" :pinfo="parentInfo"></my-son>
复制代码

2.在子组件中,若是向用父组件传递过来的数据,必须先定义 props 数组来接收:

<script>
  export default {
    data(){
      return {}
    },
    methods: {},
    // property 属性
    // 注意:父组件传递到子组件中的数据,必须通过 props 的接收,才能使用;
    // 经过 props 接收的数据,直接能够在页面上使用;注意:不接受,不能使用外界传递过来的数据
    props: ['pmsg1', 'pinfo']
  }
</script>
复制代码

3.接收完的props数据,能够直接在子组件的 template 区域中使用:

<template>
  <div>
    <h3>这是子组件 --- {{pmsg1}} --- {{pinfo}}</h3>
  </div>
</template>
复制代码

具体操做能够看下图:

注意:父组件传递给子组件的成员数据props都是可读数据,不要为他们从新赋值,
可是data数据都是当前属性的私有数据,并且data中的数据都是可读可写的
因为props中的数据都是只读的,因此若是想为props数据从新复制,能够把数据转存到data中,从而实现从新赋值
复制代码

因为上述进行值的传递和转存的时候,都是简单的数据类型的值,因此若是变成是引用数据类型的值,就会出现值会同时修改的状况,因此这里须要进行深拷贝操做,这里进行深拷贝操做的是利用一个包lodash:

import _ from 'lodash';
export default {
  data(){
    // 对于转存修改属性只是简单数据类型能够转,对于复杂数据类型还须要另外进行操做
    return {
      infoFromParent:this.pinfo,
      msgFromParent:_.cloneDeep(this.pmsg)
    }
  },
    // 子组件须要使用props按钮,接收外界传递过来的数据
  props:['pmsg','pinfo']
}
复制代码

经过_cloneDeep(传递一个对象),这样就能够实现深拷贝,而且返回的是一个全新的对象,修改他的值,不会影响其余的值.

父组件向子组件传递方法(属性绑定)

  1. 若是父向子传递方法,须要使用 事件绑定机制:
<my-son @func="show"></my-son>
复制代码

其中,为 子组件传递的 方法名称为 func, 具体的方法引用,为 父组件中的 show 方法 2. 子组件中,能够直接经过 this.$emit('func') 来调用父组件传递过来的方法;

子组件向父组件传值(事件绑定)

  1. 子向父传值,要使用 事件绑定机制@;

  2. 父向子传递一个方法的引用

  3. 子组件中,可使用 this.$emit() 来调用父组件传递过来的方法

  4. 在使用this.$emit()调用 父组件中方法的时候,能够从第二个位置开始传递参数;把子组件中的数据,经过实参,传递到父组件的方法做用域中;

methods: {
    // 点击子组件中的按钮,触发按钮的点击事件
    btnHandle(){
      // 在子组件中经过this.$emit()方法,触发父组件,为子组件绑定func事件

      this.$emit('func' +this.msg)
    }

  },
复制代码
  1. 父组件就能够经过形参,接收子组件传递过来的数据;

兄弟组件之间传值

注意:兄弟组件之间,实现传值,用到的技术,是 EventBus

  1. 定义模块 bus.js
import Vue from 'vue'
       
   export default new Vue()
复制代码
  1. 在须要接收数据的兄弟组件中,导入 bus.js 模块
import bus from './bus.js'
复制代码
  1. 在须要接收数据的兄弟组件中的 created 生命周期函数里, 使用 bus.$on('事件名称', (接收的数据) => {}) 自定义事件:
created(){
         // 定义事件
         bus.$on('ooo', (data)=>{
           console.log(data)
         })
       }
复制代码
  1. 在须要发送数据的兄弟组件中,导入 bus.js 模块
import bus from './bus.js'
复制代码
  1. 在须要发送数据的兄弟组件中,使用 bus.$emit('事件名称', 要发送的数据) 来向外发送数据:
import bus from './bus.js'
       export default {
           data(){
             return {
               msg: 'abcd'
             }
           },
           methods: {
             sendMsg(){
               // 触发 绑定的 事件,并向外传递参数
               bus.$emit('ooo', this.msg)
             }
           }
       }

复制代码

使用 this.$refs来获取元素和组件

1.把要获取的DOM元素,添加 ref 属性,建立一个DOM对象的引用,指定的值,就是引用的名称:

//经过ref获取的DOM元素的引用就是一个元素的DOM对象
<p ref="myElement11">这是父组件</p>
复制代码
  1. 若是要获取 某个引用所对应的 DOM对象,则直接使用 this.$refs.引用名称
console.log(this.$refs.myElement11)
复制代码
  1. 也可使用 ref 为组件添加引用;可使用 this.$refs.组件应用名称,
console.log(this.$refs.myElement11)
复制代码

3.也可使用 ref 为组件添加引用;可使用 this.$refs.组件应用名称, 拿到组件的引用,从而调用组件上的方法 和 获取组件data上的 数据;

使用 霸道的 render 函数渲染组件

  1. 若是在 vm 实例中既指定了 el 又指定了 render 函数,则会把 el 所指的的区域,替换为 render 函数中所提供的组件;

  2. 既然 render 函数会替换到 el 区域内的全部代码,也会让 template 属性失效;所以,在删减版的 vue 包中,new 出来的 Vue 实例对象,不容许 挂载 data 属性和 template 属性!

const vm = new Vue({
  el: '#app',
  // createElements 形参是一个方法,专门用于渲染一个组件,并替换掉 el 区域
  /* render: function(createElements){ return createElements(App) }, */
  // 这是 render 的终极格式
  // 被render渲染的组件,叫作 根组件
  // 什么是根组件:【不论浏览器中的页面如何切换,根组件永远都在页面上显示】
  render: h => h(App)
})

// 注意:只要在 vm 实例中,指定了 render 函数来渲染组件,那么,el 区域,就会被 render 中渲染的组件替换掉;

复制代码

基础知识五

使用标签实现组件切换

  1. 是Vue提供的;做用是 把 is 指定的 组件名称,渲染到 内部
  2. 身上有一个 :is属性
<template>
  <div>
    <h1>App 根组件</h1>
    <button @click="comName='my-home'">Home</button>
    <button @click="comName='my-movie'">Movie</button>
    <!-- 能够经过 component 的is属性,动态指定要渲染的组件 -->
    <component :is="comName"></component>
  </div>
</template>

<script>
import Home from './coms/Home.vue'
import Movie from './coms/Movie.vue'
export default {
  data() {
    return {
      // 默认是展现home属性的
      comName: 'my-home'
    }
  },
  components: {
    'my-home': Home,
    'my-movie': Movie
  }
}
</script>
复制代码

SPA单页应用

锚连接及常规url的区别

  1. 普通的URL地址:会刷新整个页面;会追加浏览历史记录;
  2. 锚连接:不会触发页面的总体刷新;会追加浏览历史记录;(锚连接是页面内的跳转)

什么是SPA,为何有SPA

  • 概念定义:SPA英文全称是Single Page Application, 中文翻译是 “单页面应用程序”;
  • 通俗的理解是:只有一个Web页面的网站;网站的全部功能都在这个惟一的页面上进行展现与切换;
  • 特色:
    • 只有一个页面
    • 浏览器一开始请求这个页面,必须加载对应的HTML, CSS, JavaScript
    • 用户的全部操做,都在这惟一的页面上完成
    • 页面数据都是用Ajax请求回来的
  • 好处:
    • 实现了先后端分离开发,各司其职;提升了开发效率;
    • 用户体验好、快,内容的改变不须要从新加载整个页面;
  • 缺点:
    • 对SEO不是很友好,由于页面数据是Ajax渲染出来的; (Server Side Render)服务器端渲染;
    • 刚开始的时候加载速度可能比较慢;项目开发完毕以后,能够单独对首屏页面的加载时间作优化;
    • 页面复杂度比较高,对程序员能力要求较高;

原生实现SPA

使用 component 标签的:is属性来切换组件

总结:单页面应用程序中,实现组件切换的根本技术点,就是 监听 window.onhashchange 事件;

路由

什么是路由:路由 就是 对应关系;

  1. 后端路由的定义:URL地址 到 后端 处理函数之间的关系;
  2. 前端路由的定义:hash 到 组件 之间的对应关系;
  3. 前端路由的目的:为了实现单页面应用程序的开发;
  4. 前端路由的三个组成部分:
    • 连接
    • 组件
    • 连接 和 组件之间的对应关系

在 vue 中使用 vue-router【重点】

  1. 安装导入并注册路由模块:
    • 运行 npm i vue-router -S 安装路由模块
    • 在 index.js 中导入并注册路由模块
// 导入路由模块
         import VueRouter from 'vue-router'
         // 注册路由模块(把路由模块安装到Vue上)
         Vue.use(VueRouter)
复制代码
  1. 建立路由连接:
<!-- router-link 就是 第一步,建立 路由的 hash 连接的 -->
<!-- to 属性,表示 点击此连接,要跳转到哪一个 hash 地址, 注意:to 属性中,你们不须要以 # 开头 -->
<router-link to="/home">首页</router-link>
<router-link to="/movie">电影</router-link>
<router-link to="/about">关于</router-link>
复制代码

3.建立并在 index.js 中导入路由相关的组件:

import Home from './components/Home.vue'
import Movie from './components/Movie.vue'
import About from './components/About.vue'
复制代码

4.建立路由规则

// 建立路由规则(对应关系)
const router = new VueRouter({ // 配置对象中,要提供 hash 地址 到 组件之间的 对应关系
  routes: [ // 这个 routes 就是 路由 规则 的数组,里面要放不少的对应关系
    // { path: 'hash地址', component: 配置对象 }
    { path: '/home', component: Home },
    { path: '/movie', component: Movie },
    { path: '/about', component: About }
  ]
})
// 建立的 router 对象,千万要记得,挂载到 vm 实例上
const vm = new Vue({
  el: '#app',
  render: c => c(App),
  router // 把 建立的路由对象,必定要挂载到 VM 实例上,不然路由不会生效
})
复制代码

5.在页面上放路由容器

<!-- 这是路由的容器,未来,经过路由规则,匹配到的组件,都会被展现到这个 容器中 也就是切换的内容会在下面的这个区域进行显示 -->
<router-view></router-view>
或者是直接写成是单闭合标签
<router-view />
复制代码

路由规则的匹配过程

  1. 用户点击 页面的 路由连接router-link,点击的一瞬间,就会修改 浏览器 地址栏 中的 Hash 地址;
  2. 当 hash 地址被修改之后,会当即被 vue-router 监听到,而后进行 路由规则的 匹配;最终,找到 要显示的组件;
  3. 当 路由规则匹配成功之后,就找到了 要显示的 组件,而后 把 这个组件,替换到 页面 指定的 路由容器router-view 中

设置路由高亮的两种方式

  1. 经过路由默认提供的router-link-active, 为这个类添加本身的高亮样式便可;
<style lang="less" scoped> .router-link-active { color: red; font-weight: bold; } </style>

复制代码
  1. 经过路由构造函数,在传递路由配置对象的时候,提供 linkActiveClass 属性,来覆盖默认的高亮类样式;
// 3. 建立路由实例对象
const router = new VueRouter({
  routes: [
    // 路由?  就是对应关系
    // 前端路由? hash => 组件 之间的对应关系
    // vue 中路由的格式     { path, component }
    // path 路由hash地址中,路径必须以 / 开头,并且必须是小写,并且不能带空格
    { path: '/home', component: Home },
    { path: '/movie', component: Movie },
    { path: '/about', component: About },
    { path: '/me', component: Me }
  ],
  linkActiveClass: 'my-active' // 若是你们作项目时候, 用到的 UI 组件库中,提供了默认的高亮效果
})


//在页面上的显示类名以下:

.my-active {
  color: #007ACC;
  font-weight: 700;
}
复制代码

嵌套路由(子路由)

  1. 在对应的路由组件中,新增 router-link 路由连接;
  2. 建立 router-link 对应要显示的组件;
  3. 在对应的路由规则中,经过 children 属性,定义子路由规则:
const router = new VueRouter({
  routes: [
    // 路由? 就是对应关系
    // 前端路由? hash => 组件 之间的对应关系
    // vue 中路由的格式 { path, component }
    // path 路由hash地址中,路径必须以 / 开头,并且必须是小写,并且不能带空格
    // 在路由规则中,经过 redirect 属性,指向一个新地址,就可以实现路由的重定向
    { path: '/', redirect: '/home' },
    { path: '/home', component: Home },
    { path: '/movie', component: Movie },
    // 在某个路由规则中,如何嵌套子路由规则? path 和 component 平级,还有个 children 属性
    // children 属性 是一个数组, 做用,就是来嵌套子路由规则的
    {
      path: '/about',
      component: About,
      redirect: '/about/tab1',
      children: [
        { path: '/about/tab1', component: Tab1 },
        { path: '/about/tab2', component: Tab2 }
      ]
    },
    { path: '/me', component: Me }
  ],
  linkActiveClass: 'my-active' // 若是你们作项目时候, 用到的 UI 组件库中,提供了默认的高亮效果
})

复制代码

路由传参

经过属性绑定实现路由传参,也就是在路由规则的参数项以前加冒号实现路由传参

<!-- 当router-link的to地址,要动态进行拼接的时候,那么,必定要把 to 设置成属性绑定的形式 -->
      <router-link v-for="item in mlist" :key="item.id" :to="`/mdetail/${item.id}/${item.name}`" tag="li">{{item.name}}</router-link>
复制代码

可是仍是可能会出现参数不固定的状况

const router = new VueRouter({
  routes: [
    { path: '/', component: MovieList },
    // 把路由规则中, 参数项位置,前面加上 : 表示这是一个参数项
    // props: true 表示,为当前路由规则,开启 props 传参
    { path: '/mdetail/:id1/:name2', component: MovieDetail, props: true }
  ]
})

复制代码
  1. 能够在组件中,直接使用this.route.params 来获取参数;【写起来太麻烦,不推荐】
this.route是一个路由的参数对象, this.$router是路由的导航对象
  2. 也能够开启路由的 props 传参,来接收路由中的参数;【推荐方式】
    1. 在须要传参的路由规则中,添加 props: true
{ path: '/movie/:type/:id', component: movie, props: true }
复制代码
  1. 在 对应的组件中,定义 props 并接收路由参数
const movie = {
                template: '<h3>电影组件 --- {{type}} --- {{id}}</h3>', // 使用参数
                props: ['type', 'id'] // 接收参数
              }
复制代码

命名路由

什么是命名路由: 就是为路由规则,添加了一个 name ;

  1. 什么是命名路由
  2. router-link中经过路由名称实现跳转
  3. 命名路由使用 params属性传参
<!-- 使用 命名路由实现跳转 -->
       <router-link v-for="item in mlist" :key="item.id" :to="{name: 'moviedetail', params: {id1: item.id, name2:item.name}}" tag="li">{{item.name}}</router-link> 
复制代码

编程式(JS)导航

以前所学的router-link是标签跳转;

除了使用router-link是标签跳转以外,还可使用Javascript来实现路由的跳转;

  1. 什么是编程式导航
    • 使用vue-router提供的JS API实现路由跳转的方式,叫作编程式导航;
  2. 编程式导航的用法

//跳转到指定的路由规则中

  • this.$router.push('路径的地址')

//能够前进和后退

  • this.$router.go(n)

//能够前进

  • this.$router.forward()

//能够后退

  • this.$router.back()

关于路由的方法的总结

  • this.$route是路由参数对象
  • this.$router是路由导航对象
  • vm实例上的router属性,是挂载路由对象的
  • 在new VueRouter(/配置对象/)的时候,配置对象中,有一个routes属性,是建立路由规则的
  • router单独的写在 vm实例对象里面,表示挂载路由

path 是要匹配的hash值, component 要展现的组件 redirect 要重定向的路由 props 开启props传参 name 命名路由 children 嵌套子路由

路由导航守卫

  • 案例需求:只容许登陆的状况下访问 后台首页 ,若是不登陆,默认跳转回登陆页面;
  • API语法:
// 参数1:是要去的那个页面路由相关的参数
      // 参数2:从哪一个页面即将离开
      // 参数3:next 是一个函数,就至关于 Node 里面 express 中的 next 函数
      // 注意: 这里的 router 就是 new VueRouter 获得的 路由对象
      router.beforeEach((to, from, next) => { /* 导航守卫 处理逻辑 */ })
复制代码

案例核心代码:

// 经过 路由导航守卫, 控制有权限页面的访问, 只有登陆之后,才容许访问高级的页面
router.beforeEach((to, from, next) => {
  // to.path 表示咱们下一刻要访问哪一个地址
  // console.log(to)
  // from.path 表示咱们上一刻,所访问的是哪一个地址
  // console.log(from)

  // next() 直接调用,表示放行
  // next()

  // 若是 要访问的地址,是 /login, 证实用户要去登陆, 没有必要拦截,直接放行
  if (to.path === '/login') return next()
  // 若是用户访问的不是 登陆页面,则 先尝试从sessionStorage中获取 token 令牌字符串
  const tokenStr = window.sessionStorage.getItem('token')
  // 若是没有 token 令牌,则 强制用户跳转到登陆页
  if (!tokenStr) return next('/login')
  // 若是有令牌,则直接放行
  next()
})
复制代码

关于token验证问题

token是一个令牌,是服务器端发送过来的客户端必须经过登陆,才能获取这个令牌,

watch 监听

  • watch 监听的特色:监听到某个数据的变化后,侧重于作某件事情;

    • 只要被监听的数据发生了变化,会自动触发 watch 中指定的处理函数;
  • 案例:登陆 密码 的长度检测

  • 密码长度小于8位,字体为红色;大于等于8位,字体为黑色;

export default {
  data() {
    return {
      uname: '',
      upwd: ''
    }
  },
  // watch 是监听 data 中数据的变化, 侧重于作某件事件
  watch: {
    upwd(newVal, oldVal) {
      if (newVal.length < 8) {
        this.$refs.pwdDOM.style.color = 'red'
      } else {
        this.$refs.pwdDOM.style.color = ''
      }
    }
  }
}
复制代码

computed 计算属性

计算属性特色:同时监听多个数据的变化后,侧重于获得一个新的值;

  • 只要依赖的任何一个数据发生了变化,都会自动触发计算属性的从新求值;
export default {
  data() {
    return {
      firstname: '',
      lastname: ''
    }
  },
  // 计算属性
  computed: {
    // 定义一个计算属性,叫作 fullName
    // 注意: 全部的计算属性,在定义的时候, 都要被定义为 function,
    // 可是,在页面上使用计算属性的时候, 是直接看成普通的 变量 来使用的,而不是看成方法去调用的!!!
    // 特色:只要计算属性的 function 中,依赖的 任何一个数据发生了变化,都会对这个计算属性,从新求值
    fullName: function() {
      return this.firstname + '-' + this.lastname
    }
  }
}

复制代码

应用

若是页面须要访问一个数据,这个数据比较复杂,是须要经过其余data通过复杂步骤制做出来的,那么就能够经过“计算属性”简化得到该数据

补充:Vue自己支持模板中使用复杂表达式表现业务数据,可是这会使得模板内容过于杂乱,若是确有需求,能够经过computed计算属性实现

与methods方法的区别:

computed计算属性自己有“缓存”,在关联的data没有变化的状况下,后续会使用缓存结果,节省资源

methods方法没有缓存,每次访问 方法体 都须要加载执行,耗费资源

复制代码

使用 vue-cli 快速建立 vue 项目

为何要使用 vue-cli 建立项目:

  • 在终端运行一条简单的命令,便可建立出标准的 vue 骨架项目;
  • 没必要本身手动搭建 vue 项目基本结构,省时省力;
  • 没必要关心 webpack 如何配置,只关注于项目代码的开发;

webpack 中 省略文件后缀名 和配置 @ 路径标识符

省略文件扩展名:

  • 打开 webpack.config.js,在导入的配置对象中,新增 resolve 节点;
  • 在 resolve 节点中,新增 extensions 节点:
resolve: {
    // resolve 节点下的 extensions 数组中,能够配置,哪些扩展名能够被省略
    extensions: ['.js', '.vue', '.json']
}
复制代码

修改完配置之后,从新运行 npm run dev 查看效果;

配置 @ 指向 src 目录:

resolve: {
    alias: {
      '@': path.join(__dirname, './src') // 让 @ 符号,指向了 项目根目录中的 src
    }
  }
复制代码

基础知识六

自定义指令

全局自定义指令

  • 概念:在全局任何组件中均可以被调用的自定义指令,叫作全局自定义指令;
  • 语法:Vue.directive('全局自定义指令名称', { /* 自定义指令配置对象 */ })
// Vue.directive('全局指令名称', { /*指令的配置对象*/  })

// 注意:自定义指令名称以前,不须要手动添加 v- 前缀
Vue.directive('red', {
  // 只要指令被解析指令了,就会优先调用指令中的 bind 方法
  bind(el) {
    // 只要bind被指向了,那么el,就是它所绑定到的 UI 元素
    // el 是原生DOM对象,也正是由于他是原生的DOM对象,因此他才能够经过style.color的方式修改样式
    
    el.style.color = 'red'
  }
})
复制代码

私有自定义指令

概念:只有指令所属的组件中,才能够被正常调用的指令,叫作私有自定义指令;

// 私有自定义指令的定义节点
  directives: {
    // 指令名称: { /配置对象/ }
    blue: {
      bind(el) {
        el.style.color = 'blue'
      }
    }
  }
复制代码

指令配置对象中 bind 和 inserted 的区别

  • bind 方法:
    • 绑定当前指令的元素,在内存中被建立的时候就会被当即调用;
    • 推荐把样式相关的设置,都定义在 bind 方法中;
  • inserted 方法:
    • 绑定当前指令的元素,被插入到DOM树以后才会被调用;
    • 推荐把行为相关的设置,都定义在 inserted 方法中;
  • 演示 bind 和 inserted 的区别:
    • 在终端中打印 el.parentNode 便可; 在bind中输出的el.parentNode为null, 可是在inserted中输出的是他的父节点
Vue.directive('focus', {
  // bind 表示指令第一次被解析执行时候调用,此时,这个 DOM 元素,尚未被append到父节点中;
  // 此时只是在内存中存储着,因此还你没有渲染到页面上
  bind(el) {
    // el.focus()
    // console.log(el.parentNode),null
  },
  // inserted 会在元素被插入到父节点以后,执行,此时已经渲染到页面之上了
  inserted(el) {
    // 定义 文本框得到焦点的指令,只能经过 inserted 来实现
    // 由于 bind方法 和 inserted方法 的执行时机不同
    el.focus()
  }
})

// 总结:若是只是单纯的为元素设置样式,尽可能写到 bind 中
// 若是要设置JS行为,好比文本框获取焦点,这种行为,尽可能写到 inserted 中

复制代码

自定义指令传参

Vue.directive('color', {
  // 经过 形参中的 binding 来接收指令传递过来的数据
  // 全部经过=传过来的值都是在binding中存储着
  // 传递过来的参数,是 binding.value 属性
  bind(el, binding) {
    // console.log(binding.value)
    el.style.color = binding.value
  }
})
复制代码

插槽

定义:定义子组件的时候,在子组件内部刨了一个坑,父组件想办法往坑里填内容;

单个插槽(匿名插槽)

  1. 定义插槽:在子组件做用域中,使用 定义一个插槽;
  2. 使用插槽:在父做用域中使用带有插槽的组件时,组件内容区域中的内容,会插入到插槽中显示;
  3. 注意:在一个组件的定义中,只容许出现一次匿名插槽

Son.vue子组件代码:

<template>
    <div>
        <h4>这是子组件</h4>
        <p>哈哈哈</p>
        <!-- 没有name属性的插槽,称为是匿名插槽 -->
        <slot></slot>
        <!-- 注意:在同一个组件中,只容许定义一次插槽 -->
        <!-- <slot></slot> -->
        <p>heiehei</p>
    </div>
</template>
复制代码

APP.vue主组件代码展现:

<template>
    <div>
        <h1>这是父组件</h1>
        <hr>
        <!-- 在子组件的内部放置内容 -->
        <!-- 默认状况下载组件内容中,定义的信息都会被显示到匿名插槽中 -->
        <my-son>
            <img src="./images/土拨鼠啊.gif" alt="">
            <img src="./images/老王.png" alt="">
            <h3>6666</h3>
        </my-son>
    </div>
</template>
复制代码

多个插槽(具名插槽)

  1. 定义具名插槽:使用 name 属性为 slot 插槽定义具体名称;
<template>
    <div>
        <h1>这是子组件</h1>
        <p>啊,五环</p>
        <!-- 匿名插槽 -->
         <slot></slot>
        <p>你比四环多一环</p>
        <!-- 具名插槽 -->
        <slot name="s2"></slot>
        <p>啊,五环</p>
        <slot name="s3"></slot>
        <p>你比七环少两环</p> 
    </div>
</template>
复制代码
  1. 使用具名插槽:在父做用域中使用带有命名插槽的组件时,须要为内容指定 slot="插槽name" 来填充到指定名称的插槽;
<template>
  <div>
    <h1>这是父组件</h1>
    <hr />
    <my-son>
      <!-- 默认状况下指定的元素会被插入到匿名插槽中 -->
      <img src="../03默认插槽/images/一脸懵逼表情包.jpg" alt />
      <img slot="s2" src="../03默认插槽/images/土拨鼠啊.gif" alt />
      <img src="../03默认插槽/images/老王.png" alt />
      <img slot="s3" src="../03默认插槽/images/擅用百度.jpg" alt="">
    </my-son>
  </div>
</template>
复制代码

做用域插槽

  1. 定义做用域插槽:在子组件中,使用 slot 定义插槽的时候,能够经过 属性传值 的形式,为插槽传递数据,
<template>
    <div>
        <h4>这是子组件</h4>
        <slot smsg="hello Vue" sinfo="你好"></slot>
        <p>
            ~~~~~~~~~~~~~~
        </p>
        <slot name="s2" :umsg="m1" :uinfo="m2">

        </slot>
    </div>
</template>
<script>
export default {
    data(){
        return {
            m1:'abcd',
            m2:'123456'
        }
    }
}
</script>
复制代码
  1. 使用做用域插槽:在父做用域中,经过定义 slot-scope="scope" 属性,接收并使用 插槽数据;
  2. 注意:同一组件中不一样插槽的做用域,是独立的!
<template>
    <div>
        <h1>这是父组件</h1>
        <hr>
        <my-son>
            <h6 slot-scope="scope">{{scope}}</h6>
            <!-- <h3 slot="s2" slot-scope="scope">{{scope}}</h3>
            <h3 slot="s2" slot-scope="scope">{{scope}}</h3> -->
            <!--  若是要接收做用域插槽中的数据,并且渲染为多个标签,
            则必须在多个标签以外,包裹一个父元素,进行接收插槽中的数据
            -->
            <!-- 注意 template只起到包裹元素的做用,不会被渲染为任何标签-->
            <template slot="s2" slot-scope="scope">
                <h3>{{scope.uinfo}}</h3>
                <h3>{{scope.umsg}}</h3>
            </template>
        </my-son>
    </div>
</template>
复制代码

element-ui

待更新....

1.element-ui 是 饿了么 前端团队,开源出来的一套 Vue 组件库;

2.完整引入 Element-UI 组件:

1. 运行 yarn add element-ui -S 安装组件库
2. 在 index.js 中,导入 element-ui 的包、配套样式表、而且安装到Vue上:
复制代码
// 导入 element-ui 这个包
import ElementUI from 'element-ui'
// 导入 配套的样式表
import 'element-ui/lib/theme-chalk/index.css'

// 把 element-ui 安装到 Vue 上
Vue.use(ElementUI)
复制代码

3.按需导入和配置 Element-UI :

  1. 运行 npm i babel-plugin-component -D 安装支持按需导入的模块;
  2. 打开 .babelrc 配置文件,修改以下:
{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties", 
    + [
    + "component",
    + {
    +   "libraryName": "element-ui",
    +   "styleLibraryName": "theme-chalk"
    + }
  ]]
}
复制代码

使用vue-cli快速初始化vue项目

$ npm install -g vue-cli        // 全局安装脚手架工具
$ vue init webpack my-project   // 初始化项目
$ cd my-project                 // 切换到项目根目录中
$ npm install                   // 安装依赖包
$ npm run dev                   // 一键运行项目
复制代码

ESLint 语法检查规范

  1. 声明可是未使用的变量会报错
  2. 空行不能连续大于等于2
  3. 在行结尾处,多余的空格不容许
  4. 多余的分号,不容许
  5. 字符串要使用单引号,不能使用双引号
  6. 在方法名和形参列表的小括号之间,必须有一个空格
  7. 在单行注释的 // 以后,必须有一个空格
  8. 在每个文件的结尾处,必须有一个空行
  9. import语句必须放到最顶部
  10. etc...

如何配置VSCode帮咱们自动把代码格式为须要的样子

  1. 在安装 Vetur 插件
  2. 安装 Prettier - Code formatter 插件
  3. 打开 vs code 的 文件 -> 首选项 -> 设置,在用户设置最底部的合适位置,添加以下配置:
// 使用 ESLint 规则
"prettier.eslintIntegration": false,
// 每行文字个数超出此限制将会被迫换行
"prettier.printWidth": 100,
// 使用单引号替换双引号
"prettier.singleQuote": true,
// 格式化文件时候,不在每行结尾添加分号
"prettier.semi": false,
// 设置 .vue 文件中,HTML代码的格式化插件
"vetur.format.defaultFormatter.html": "prettier"
复制代码
  1. 重启VS Code让插件和配置生效!
  2. 打开vue-cli生成的项目中,.eslintrc.js配置文件,找到 rules 节点, 将以下语法规则,粘贴到 rules 配置中:
相关文章
相关标签/搜索