Vue1

作者: fastwe | 来源:发表于2018-11-26 22:04 被阅读0次

    第一章

    Vue概述

    what? Vue是实现UI层的渐进式js框架,核心库关注视图层,简单的ui构建,复杂的路由控制、网络通信...

          Vue.js(读音 /vjuː/,类似于view)是一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue 的核心库只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与单文件组件和 Vue 生态系统支持的库结合使用时,Vue 也完全能够为复杂的单页应用程序提供驱动,是轻量级的 MVVM 框架

    从最简单的数据处理,到数据交互,到DOM操作,到路由处理等,VueJS都有完整的解决方案

    why?  ① Vue借鉴了Angular指令和React组件的优势开发出来的

          ② Vue渐进式的框架,学习曲线比较缓和,官方提供了全套的技术支持

          ③ Vue 效率比较高,代码组织非常轻松

          ④ 单文件(以 .vue 结尾),其中包含了一个组件所需要用到的html/css/js

          ⑤ Vue是个人开发者开发的框架,比公司开发的框架发布版本、解决问题的速度更快

          ⑥ 支持jsx、js、ES6、typescript,支持的语法比较多

          ⑦ vue2.0引入了Virtual DOM(虚拟DOM),页面更新效率更高,速度更快

    where? 可以做 ui 视图层、实现SPA、也可以加入路由、网络、状态管理等,有非常多的官方工具

           IE9及更高版本才支持

    问题: Vue和jQuery之间的区别?

    Vue是声明式,是通过描述状态与视图之间的映射关系,然后通过这样的一个映射关系来操作DOM,或者说是用这样的映射关系来生成一个DOM节点插入到页面中去

    jQuery是命令式,使用jQuery操作DOM去局部更新视图,做到局部渲染,命令式就是想做什么就直接去调用方法直接做,简单直接

    在逻辑上,Vue只有一个行为: 就是状态,而jQuery是两个行为: 状态+DOM,Vue可以让开发者把关注点只放在状态的维护上,不需要关系操作DOM,降低了代码维护的复杂度

    https://cn.vuejs.org                         //官方教程

    https://github.com/vuejs/vue-cli             //用CLI搭建vue脚手架

    https://github.com/vuejs/vue-devtools        //vue调试工具

      下载仓库→npm install下载依赖→npm run build编译→Chrome→更多工具→扩展程序

      →将shells/chrome文件夹拖过去,在F12(开发者工具)中看到Vue即可(chrome文件夹不能删)

    https://router.vuejs.org/zh-cn               //路由手册

    https://github.com/pagekit/vue-resource      //vue-resource文档

    https://github.com/vuejs/awesome-vue         //Vue的其它库

    how?

    搭建Vue开发环境

    方式1  借助于vue-cli(Vue的脚手架工具,30kB的gzipped)

    npm install webpack -g              //全局安装webpack

    npm install --global vue-cli        //全局安装 vue-cli

    vue -V          //查询安装的vue的版本

    vue list        //显示可用的模板

    vue init webpack(模板名)  myapp(项目名)        //创建一个基于 webpack 模板的完整项目

    初始化设置:

    Target directory exists. Continue? (Y/n)直接回车默认会下载 vue2.0模板(可能需要连代理)

    Project name (vue-test)    直接回车默认

    Project description (A Vue.js project)    直接回车默认

    Use ESLint to lint your code      是否使用ESLink检查代码(可选N)

    Author  写上自己的名字

    cd 项目名           //切换到项目

    npm install         //安装项目依赖(自动安装package.json中指定的文件到node_modules文件夹中)

    npm run dev         //运行,调试模式(已自动设置热更新,在src中开发会自动更新)

    npm run build       //发布,发布模式(编译、打包)

    在手机上查看vue.js项目:

    ① 修改config/index.js文件

       module.exports = {

         dev: {

           host: '0.0.0.0'    //原为: host: 'localhost'

         }

       }

    ② 查看本机ip(在命令行输入ipconfig)

    ③ 将项目url中的localhost修改为此ip即可在手机端查看此项目(手机和电脑需要在同一局域网下)

    import Vue from 'vue'

    import VueRouter from 'vue-router'

    import VueResource from 'vue-resource'    //这三个都要在单文件的main.js中引入注册才能使用

    主目录:

    index.html      首页,可自由修改(可设置视口、引入zepto、md5、echarts等,发布时会被单独分开)

    package.json    可修改name、版本、描述、作者,项目配置文件,指定项目的依赖

    README.md       描述文件,可修改

    config          配置,启动相关,里面的index.js可修改

    node_modules    项目依赖的包

    static          放置静态资源的文件夹(图片、js、css文件等)

    build/webpack.base.conf.js    基础配置文件,配置别名alias('@':resolve('src'),将@解析为src)

    dist            发布的文件目录,即webpack编译输出的目录

    src文件夹       主要在此开发(开发目录)

      main.js       入口文件,初始化vue实例并设置需要使用的插件(比如less、css,发布时不会被分开)

                      比如: require('./assets/css/adapter.less');  会被合成压缩为一个文件

      App.vue       主组件,所有页面都是在App.vue下进行切换的,可以将所有的路由看作它的子组件

      router        配置路由组件

     components  功能组件,用来与用户交互

    mockServer    模拟后端服务,即用webpack开发时模拟调用的后端服务(用nodejs服务模拟)

    libs          放置公共的文件,如js、css、img、font等

    通常一个前端项目会分有一个 src 目录和 dist 目录,src放置源码,dist放置编译后的代码

    static存放第三方静态文件

    src/main.js:全局配置

    Vue.config.devtools=true;    //是否允许vue-devtools检查代码,方便调试

                                 //开发版本默认为true,生产版本默认为false

    Vue.config.productionTip=false;        //是否需要vue启动时生成生产提示

    build/webpack.prod.conf.js: 或config/index.js:

    将 productionSourceMap: true, 改为false,不输出.map文件

    npm install less less-loader --save     //安装less及其依赖项

    方式2  直接引入 vue.js 文件到项目工程中

    ________________________________________________________________________________________________

    一、vue编译打包后,css的引用路径错误:

    1、在webpack.prod.conf.js文件里的output里面添加: publicPath: './'

    2、在utils.js文件里添加:

      return ExtractTextPlugin.extract({

        use: loaders,

        fallback: 'vue-style-loader',

        publicPath: '../../',

      })

    3、在config/index.js文件里,添加: assetsPublicPath: './'

    二、使用Object.freeze()可以冻结一个对象,冻结后不能向对象添加新的属性,不能修改已有属性的值,Vue遇到这类对象时,不会为对象加上getter、setter等数据劫持的方法,可以节省浏览器CPU开销,比较适合展示类的场景

    三、v-else指令必须紧跟在v-if或者v-else-if元素的后面,否则它将不会被识别,当v-if与v-for一起使用时,v-for具有比v-if更高的优先级

    所以当循环的集合是为空时,v-if后面的v-else不会被识别

    解决: 可以将一个<template>元素当做不可见的包裹元素,并在上面使用v-if进行渲染分组,最终的渲染结果将不包含<template>元素

    <template v-if="list!=null && list.length>0">

      <div v-for="item in list"></div>

    </template>

    <div v-else></div>

    注意: v-show不支持template元素

    四、判断输入框是否只读

    <input :name="item.ename" type="text" :readonly="item.readonly==1" />

    五、绑定内联样式

    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

    六、去掉元素与元素之间的空格

    在vue-loader中: vue:{ preserveWhitespace:false }

    七、问题: vue-loader会对style scoped中的每个选择器添加一个自定义属性,但挂载实例外的元素无法添加自定义属性,导致选择器无效

        解决: 在<style type="text/css" scoped></style>外添加一个<style></style>写对应样式

    _______________________________________________________________________________________________

    使用vue

    1、vue基本用法

    new Vue({

     el:"#example",         //将实例与该选择器对应的元素绑定在一起(数据、组件会加载在其中)

                               也可用class:'.example'、标签:'div',vue2.0不允许挂在到body/html上

     data:{ },              //初始化数据(所有的变量都要在 data 对象中初始化)

     methods:{ },          //方法函数 都要放在 methods 对象中

              方法里的this指new Vue的返回值,this.变量名,可获取/修改变量(data/methods...的成员)

     directives:{ }        //指令放在directives中

    })

    2、vue自带指令

    循环遍历: ————— 遍历得到的数据,后代元素可以直接使用,使用v-for的元素会遍历出现多次

    v-for = "临时变量名 in 集合"                          //集合可以是对象或数组

    v-for = "(value值, key下标或属性) in 集合"

        <li v-for="tmp in list">

          <p>{{tmp}}</p>

        </li>

    :key="key"可为遍历的每个元素绑定唯一的key属性,当数据变化时,可重用之前的元素,提高渲染效率

    选择  v-if    v-else-if    v-else    添加分支处理不同的选择结果,添加/移除在DOM树上

          v-show    控制元素的显示/隐藏(不移除)

    <divv-cloak>{{msg}}</div>           可以隐藏未编译的标签直到实例准备完毕再编译

                                         需要与css配合使用: [v-cloak]{ display:none; }

    <div v-once><p>{{msg}}</p></div>

          只渲染元素和组件一次,随后的重新渲染,元素/组件及其所有的子节点将被视为静态内容并跳过

    绑定    v-bind  将变量的值,绑定到组件的某一个属性上(如href/width/height...)

    <img v-bind:src="'../img/'+imgName" />        //用字符串拼接,将变量绑定到属性上

    <imgv-bind:src="nowImage" />         //直接写变量,绑定到属性上

    <a :href="urlName">天猫</a>         //简写,省略v-bind(冒号不省略)

    <img src="../img/1.jpg" />                //不带变量可以不用绑定

    <img v-bind:src="'../img/'+imgName" />    //绑定常量,需要在引号内加单引号

    <img v-bind:src="nowImage" />             //绑定变量,直接放在引号内即可

    <button v-on:click="handleClick">clickMe</button>    //为元素绑定事件处理函数,不传参可不加()

    <button@click="handleClick">clickMe</button>       //简写,将  v-on:  换成@

                                                           也可以将函数改为其它操作(如赋值)

    Vue.js 为 v-on 提供了事件修饰符,通过由点(.)表示的指令后缀来调用修饰符

    <a v-on:click.stop="doThis"></a>                阻止单击事件冒泡

    <form v-on:submit.prevent="onSubmit"></form>    提交事件不再重载页面

    <form v-on:submit.prevent></form>           只有修饰符

    <div v-on:click.capture="doThis">...</div>  添加事件侦听器时使用事件捕获模式

    <div v-on:click.self="doThat">...</div>     只当事件在该元素本身(而不是子元素)触发时触发回调

    <a v-on:click.once="doThis"></a>           点击事件将只会触发一次

    <a v-on:click.stop.prevent="doThat"></a>    修饰符可以串联

    注: 使用修饰符时,顺序很重要,相应的代码会以同样的顺序产生

        所以,用@click.prevent.self会阻止所有的点击,而@click.self.prevent只会阻止元素上的点击

    methods: {    //在 methods 对象中定义事件的方法

      handleClick: function(e){          //@click="handleClick"不需要传参

        console.log(this.name)           // this 指向当前 Vue 实例

        console.log(e.target.tagName)    // e 指向当前的原生DOM元素

     }

    }

    vue可以给class或style属性绑定对象或数组,且可以与普通的class属性共存

    <div class="static" v-bind:class="{active: isActive, 'text-danger': hasError}"></div>

                                        //active和'text-danger'的值为真时会添加class,否则会移除

                                        //isActive/hasError也可换成Boolean类型结果的表达式

    <div v-bind:class="classObject"></div>    //也可以绑定数据里的一个对象(对象的属性作为类名)

    data: {        //要在data中初始化变量为Boolean类型,当变量变化时,class会随之变化

      isActive: true,

      hasError: false,

      classObject: {

        active: true,

        'text-danger': false

      }

    }

    可以为select指定默认的option:

    在option上绑定 :selected="sel.id == item.id" 返回true或false来指定默认值

    在Vue 2.0中,为自定义组件绑定原生事件必须使用 .native 修饰符:

    <my-component @click.native="handleClick">Click Me</my-component>

    数据绑定:

    用双花括号包裹变量可将数据显示在视图上,比如  <p>{{msg变量}}</p>

    v-model是双向数据绑定的指令,可将视图中用户操作的结果绑定到数据上

      <input type="text" v-model="uName"/>

      <h1>{{uName}}</h1>

    v-model 的修饰符:

    .lazy

    在默认情况下,v-model 在 input(输入后,立即触发,无延迟) 事件中同步输入框的值与数据,但你可以添加一个修饰符 lazy,从而转变为在 change(失焦时触发,有延迟) 事件中同步

    <input v-model.lazy="msg"/>        //"change"取代"input"事件,进行更新

    .number

    如果想自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值),可以添加一个修饰符 number 给 v-model 来处理输入值

    <input v-model.number="age" type="number">              //输入字符串转为数字

    这很有用,因为在type="number"时,HTML中输入的值也总是会返回字符串类型

    .trim

    如果要自动过滤用户输入的首尾空格,可以添加 trim 修饰符到 v-model 上过滤输入

    <input v-model.trim="msg">            //过滤掉首尾的空格

    _______________________________________________________________________________________________

    3、vue自定义指令

    自定义指令:  在vue的实例中,指定一个directives 属性,对应的值是一个对象,在对象中创建指令、指定指令的钩子函数

    每一个指令对应着都有自己的钩子函数(bind绑定、update更新、unbind解绑...),会在指令的调用过程中,在合适的阶段自动执行

    new Vue({

    directives:{

      change指令名:{            //创建指令

        bind: function(){ },      //绑定时调用,只调用一次

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

        update: function(){ },    //被绑定元素所在的模板更新时调用,不论绑定值是否变化

                                    (指令不会自动发起更新,要用方法发起)

        componentUpdated: function(){ },  //被绑定元素所在模板完成一次更新周期时调用

        unbind: function(){ },    //解绑时调用,只调用一次

     }

    } })

    <pv-change>指令</p>         //使用指令

    钩子函数被赋予了以下参数:

    el:  指令所绑定的元素,可以用来直接操作 DOM

    binding:  一个对象,包含以下属性:

      name:  指令名,不包括 v- 前缀

      value:指令的绑定值, 例如  v-my-directive="1 + 1", value 的值是2

      oldValue: 指令绑定的前一个值,仅在update和componentUpdated钩子中可用,无论值是否改变都可用

      expression: 绑定值的字符串形式。例如 v-my-directive="1 + 1",expression 的值是"1 + 1"

      arg:  传给指令的参数。例如  v-my-directive:foo,arg 的值是"foo"

      modifiers:  一个包含修饰符的对象。例如  v-my-directive.foo.bar,修饰符对象 modifiers 的值是{ foo: true,bar: true }

    _______________________________________________________________________________________________

    4、过滤器

    vue2.0以后的版本,官方没有提供任何的过滤器,但有创建过滤器的接口

    ① 方案1: 创建自定义过滤器

    过滤器的本质其实就是方法,可以处理输入,返回输出结果,用来实现数据的筛选、过滤、格式化

    在Vue实例的filters属性中创建过滤器:

    new Vue({

    filters:{

      filterName过滤器名: function(value,arg1,arg2...){        //value指在|前传过来的参数

       return处理后的数据                                      arg: 过滤器调用时,()中的参数

      }

    } })

    使用: 过滤器通过管道符号 |进行调用,支持多重过滤

    <p>{{ price|currency过滤器}}</p>                     //不传参时不加()

    <p>{{ price|currency过滤器('¥','@'...)}}</p>        //在()中可传多个参数

    ② 方案2: 借助第三方的过虑器

    https://github.com/wy-ei/vue-filter        //基于Vue2.0的过滤器的库

    引入对应的js文件即可使用

    _______________________________________________________________________________________________

    5、Vue 的计算属性、监听属性

    计算属性定义的是一些方法,任何的计算属性都可以在methods中定义一个相同的函数来替代它,两种方式最终的结果是相同的

    但不同的是计算属性是基于它的依赖缓存的,计算属性只有在它的相关依赖发生改变时才会重新取值

    也就是说只要 message 没有发生改变,多次访问'计算属性中的方法'会立即返回之前的计算结果,而不必再次执行函数

    计算属性的优势:

    ① 让更新更高效,可以处理复杂的业务逻辑

    ② 让代码维护更方便

    计算属性的创建:

    new Vue({

    computed:{

      handle方法: function(){ }

    } })

    使用:

    <p>{{handle方法名}}</p>

    监听属性:

    new Vue({

    watch:{

      kw: function(newValue,oldValue){    //kw: 要监听的变量名,需要初始化

                                            newValue是改变后的值,oldValue改变前的值

      },

      a: {

        handler: function(newVal, oldVal){ ... },    //当数据变化时执行的回调函数

        immediate: true                              //创建组件时立即执行一次回调函数

      },

    }})

    使用:

    <input type="text" v-model="kw变量名"/>        //双向数据绑定

    _______________________________________________________________________________________________

    6、vue实例的生命周期

    React的组件的生命周期:  mount    update    unmount

    Vue的实例的生命周期:    create   mount     update    destroy

    每个Vue实例在被创建之前都要经过一系列的初始化过程,在这个过程中,实例会调用一些生命周期钩子函数

    create:

    beforeCreate   组件实例(*.vue页面)刚被创建,组件属性计算之前,如data属性等

    created        组件实例创建完成,属性已绑定,但DOM还未生成,el属性还不存在,挂载阶段未开始

    mount:

    beforeMount    模板编译/挂载之前

    mounted        模板编译/挂载之后(不保证组件已在document中)

    update:

    beforeUpdate   组件更新之前(虚拟DOM重新渲染之前)

    updated        组件更新之后

    destroy:

    beforeDestroy  组件销毁前调用(实例仍然可用)

    destroyed      组件销毁后调用(调用后,Vue实例的所有东西都被解绑,所有事件被移除,子实例被销毁)

    使用方法:

    new Vue({

      el: "#example",

      data: {

        msg: 1

      },

     mounted: function(){        //在生命周期函数中操作数据

        setInterval(()=>{

          this.msg++;

          console.log(this.msg);

        },0)

    } })

    注意: mounted不保证所有的子组件都已挂载到DOM上,可用this.$nextTick来确保整个视图都渲染完毕

    mounted: function(){

     this.$nextTick(function(){

        //在整个视图都已渲染完毕后运行的代码

      })

    }

    _______________________________________________________________________________________________

    7、组件的创建和使用 (分为局部组件和全局组件)

    创建组件的方式:  ①局部组件  ②全局组件  ③jsx  ④使用ES6生成一个.vue结尾的文件

    注意:  组件的命名、使用建议使用烤串的写法,字母要求都是小写,不能出现大写字母,不能是标签名

    ① 局部组件的创建:

    new Vue({

    components:{

      '组件名': {

       template: '<p>局部组件<p>'

      }

    } })

    使用:

    <my-component></my-component>        //与普通的html标签用法一样

    ② 全局组件的创建:

    Vue.component('组件名',{    //使用Vue.component方法,创建在new Vue({ })之前

     template: `<ul>             //组件只能有一个顶层标签

      <li>全局组件</li>

      <全局组件></全局组件>       //组件的嵌套,全局组件可以在任意一个组件(全局/局部)中使用

      </ul>`

    });

    全局组件的使用方法与局部组件一样

    全局组件和局部组件的区别:

    全局组件可以用在任意一个组件中,可以构造更复杂的全局组件

    局部组件只能够用在 vue 实例所绑定的元素视图中

    ③ 通过jsx的语法去指定模板 (必须在命令行创建的模板中才可以,因为会有对应的依赖)

    ④ 直接创建一个以 .vue 结尾的文件(通过命令行创建的模板默认的方式)

    第二章*****************************************************************************************

    注意: 若在创建的全局组件中,需要初始化或者声明数据,指定data属性,该属性对应的值是一个方法,该方法需要返回一个对象

    Vue.component("全局组件",{

      data:function(){            //data属性对应的值是一个方法

        return { msg: ""}        //返回一个对象

      }

    });

    相当于:

    new Vue({

      el: "#example",

      data: { msg: "" }           //相当于 在vue实例中初始化数据

    })

    字符串里的内容若要换行,建议使用模板字符串

    _______________________________________________________________________________________________

    组件通信: 2种方式

    1、父向子传递数据(通过属性)

    Vue.component('father',{

      data:function(){

        return {value:""}             //初始化数据

      },

      template: `<son v-bind:msg属性="value"></son>`    //① 父组件调用子组件时,为其指定属性,

                `<son msg属性="字符串"></son>`              值为父组件的数据 或 字符串

    })

    Vue.component('son',{

     props: ['msg属性'],            //② 子组件指定props属性,对应的值是数组,

                                         数组中的字符串是从父组件传递过来的属性名称

      template: '<h1>{{msg}}</h1>'    //子组件可以使用'传递过来的属性的值',

    })                                   与'在data属性中定义的变量'用法一致

    2、子向父传递数据(通过事件)

    Vue.component('father',{

      methods:{

        resMsg方法名: function(msg接收到的值){ }  //父通过方法接收值,msg就是从子传来的值

      },

      template: `<son@toF自定义事件="resMsg方法名"></son>`  //① 在父中为子用v-on绑定自定义事件

    })

    Vue.component('son',{

      methods:{

        handleClick:function(){       //③ 在方法内调用this.$emit()方法,通过自定义事件向父传值

          this.$emit('toF自定义事件','100要传的值');    //传变量时,前加this.

        }

      },

      template:`<button @click="handleClick">向父传值</button>`    //② 点击触发事件,调用方法

    })

    _______________________________________________________________________________________________

    3、父子通信(不仅可以传属性的值,还可以传方法)

    优点:  只需要设置接收方即可,发送方不需要额外设置,方便

    缺点:  耦合度太高

    父向子传递数据,子接受数据($parent):

    在子组件中,通过'this.$parent',找到父组件,读取父组件的属性/方法

    Vue.component('parent',{        //父组件不需要额外设置

      template: `<son></son>`

    })

    Vue.component('son',{

      methods:{

        handleClick:function(){

         this.$parent.父的属性/方法   //this.$parent: 子找到父组件的实例,读取其属性/方法

        }

      },

      template: `<button @click="handleClick"></button>`    //调用方法,找到父的实例

    })

    子向父传递数据,父接收数据($refs):

    ref(reference,引用、参考),给子组件指定一个ref属性,在父组件中通过'this.$refs.指定的属性名'找到子组件

    Vue.component('parent',{

      methods:{

        handleClick:function(){

         this.$refs.son指定的属性名.子的属性/方法   //② this.refs.son: 父找到子组件的实例

        }

      },

      template: `<div>

        <sonref='指定的属性名'></son>        //① 给子组件指定一个ref属性

        <button @click="handleClick"></button>    //调用方法,找到子的实例

      </div>`

    })

    Vue.component('son',{            //子组件不需要额外设置

      data:function(){

        return { msg:'你好' }        //父可接收子的属性/方法

      },

      template: `<any></any>`

    })

    相关文章

      网友评论

          本文标题:Vue1

          本文链接:https://www.haomeiwen.com/subject/cvfcqqtx.html