vue -- 初级(一)

什么是Vue.js
Vue.js 是目前最火的一个前端框架,React是最流行的一个前端框架(React除了开发网站,还可以开发手机App, Vue语法也是可以用于进行手机App开发的,需要借助于Weex)
Vue.js 是前端的主流框架之一,和Angular.js、React.js 一起,并成为前端三大主流框架!
Vue.js 是一套构建用户界面的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。(Vue有配套的第三方类库,可以整合起来做大型项目的开发)

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

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

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

    Node(后端)中的 MVC 与 前端中的 MVVM 之间的区别
MVC 是后端的分层开发概念;
MVVM是前端视图层的概念,主要关注于 视图层分离,也就是说:MVVM把前端的视图层,分为了 三部分 Model, View , VM ViewModel
    

Vue之 - `基本的代码结构`和`插值表达式`、`v-cloak`



    {{msg}}  //使用v-aloak能够解决 插值表达式闪烁问题
    //默认v-text没有闪烁问题
   


    //创建vue实例
    var vm = new Vue({
        el:"#app",
        data:{
            msg:"欢迎学习vue",
            msg2:"

hello

",
        }
    })

Vue指令之`v-bind`的三种用法
    1. 直接使用指令`v-bind`
    2. 使用简化指令`:`
    3. 在绑定的时候,拼接绑定内容:`:title="btnTitle + ', 这是追加的内容'"`


data:{
mytitle:"这是一个自定义title"
}

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

methods:{
show:function (e) {
console.log(e)
}
}
   
   
   

{{ msg }}


    // 注意:在 VM实例中,如果想要获取 data 上的数据,或者 想要调用 methods 中的 方法,必须通过 this.数据属性名  或  this.方法名 来进行访问,这里的this,就表示 我们 new 出来的  VM 实例对象
    var vm = new Vue({
        el: '#app',
        data: {
            msg: '猥琐发育,别浪~~!',
            intervalId: null // 在data上定义 定时器Id
        },
        methods: {
            go() {
                if (this.intervalId != null) return;
                this.intervalId = setInterval(() => {
                    var start = this.msg.substring(0, 1)
                    var end = this.msg.substring(1)    // 获取到 后面的所有字符
                    this.msg = end + start    // 重新拼接得到新的字符串,并赋值给 this.msg
                }, 400)
                // 注意: VM实例,会监听自己身上 data 中所有数据的改变,只要数据一发生变化,就会自动把 最新的数据,从data 上同步到页面中去;【好处:程序员只需要关心数据,不需要考虑如何重新渲染DOM页面】
            },
            stop() { // 停止定时器
                clearInterval(this.intervalId)
                this.intervalId = null;  // 每当清除了定时器之后,需要重新把 intervalId 置为 null
            }
        }
    })
    Vue指令之`v-on的缩写`和`事件修饰符`
事件修饰符:
.stop       阻止冒泡
.prevent    阻止默认事件
.capture    添加事件侦听器时使用事件捕获模式
.self       只当事件在该元素本身(比如不是子元素)触发时触发回调
.once       事件只触发一次

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




{{msg}}

    简易计算器案例

   
   
   
   
   
    var vm = new Vue({
        el: '#app',
        data: {
            n1: 0,
            n2: 0,
            result: 0,
            opt: '+'
        },
        methods: {
            calc() { // 计算器算数的方法
                // 逻辑:
                /* switch (this.opt) {
                  case '+':
                    this.result = parseInt(this.n1) + parseInt(this.n2)
                    break;
                  case '-':
                    this.result = parseInt(this.n1) - parseInt(this.n2)
                    break;
                  case '*':
                    this.result = parseInt(this.n1) * parseInt(this.n2)
                    break;
                  case '/':
                    this.result = parseInt(this.n1) / parseInt(this.n2)
                    break;
                } */
                // 注意:这是投机取巧的方式,正式开发中,尽量少用
                var codeStr = 'parseInt(this.n1) ' + this.opt + ' parseInt(this.n2)'
                this.result = eval(codeStr)
            }
        }
    });

    在Vue中使用样式
使用class样式

样式!!!

样式!!!

样式!!!

样式!!!
data: {
    flag: true,
    classObj: { red: true, thin: true, italic: false, active: false }
    },
使用内联样式
1. 直接在元素上通过 `:style` 的形式,书写样式对象

这是一个H1


2. 将样式对象,定义到 `data` 中,并直接引用到 `:style` 中   在data上定义样式:

这是一个善良的H1


data: {
    h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' }
    }
    + 在元素中,通过属性绑定的形式,将样式对象应用到元素中:
3. 在 `:style` 中通过数组,引用多个 `data` 上的样式对象

这是一个善良的H1


data: {
    h1StyleObj: { color: 'red', 'font-size': '40px', 'font-weight': '200' },
    h1StyleObj2: { fontStyle: 'italic' }
    }

    Vue指令之`v-for`和`key`属性
1. 迭代数组
  • 索引:{{i}} --- 姓名:{{item.name}} --- 年龄:{{item.age}}

  • 2. 迭代对象中的属性
    {{val}} --- {{key}} --- {{i}}

    3. 迭代数字        i 值从 1 开始

    这是第 {{i}} 个P标签


    > 2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的。
    当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
    为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
    注意: v-for 循环的时候,key 属性只能使用 number获取string
    注意: key 在使用的时候,必须使用 v-bind 属性绑定的形式,指定 key 的值
    在组件中,使用v-for循环的时候,或者在一些特殊情况中,如果 v-for 有问题,必须 在使用 v-for 的同时,指定 唯一的 字符串/数字 类型 :key 值

        Vue指令之`v-if`和`v-show`
    v-if 的特点:每次都会重新删除或创建元素
    v-show 的特点: 每次不会重新进行DOM的删除和创建操作,只是切换了元素的 display:none 样式
    v-if 有较高的切换性能消耗 ,如果元素可能永远也不会被显示出来被用户看到,则推荐使用 v-if
    v-show 有较高的初始渲染消耗 ,如果元素涉及到频繁的切换,最好不要使用 v-if, 而是推荐使用 v-show

     


        在2.x版本中[手动实现筛选的方式](https://cn.vuejs.org/v2/guide/list.html#显示过滤-排序结果)
    列表案例:
    搜素


      // 在使用 `v-for` 指令循环每一行数据的时候,不再直接 `item in list`,而是 `in` 一个 过滤的methods 方法,同时,把过滤条件`keywords`传递进去

    • {{item.id}} -------- {{item.name}} -----  {{item.time}} -------
      删除


    search(keywords) { // 根据关键字,进行数据的搜索
        /* var newList = []
        this.list.forEach(item => {
          if (item.name.indexOf(keywords) != -1) {
            newList.push(item)
          }
        })
        return newList */
        // 注意:  forEach   some   filter   findIndex   这些都属于数组的新方法, 都会对数组中的每一项,进行遍历,执行相关的操作;
        return this.list.filter(item => {
            // if(item.name.indexOf(keywords) != -1)
            // 注意 : ES6中,为字符串提供了一个新方法,叫做  String.prototype.includes('要包含的字符串')
            //  如果包含,则返回 true ,否则返回 false
            //  contain
            if (item.name.includes(keywords)) {
                return item
            }
        })
    }

    Vue调试工具`vue-devtools`的安装步骤和使用
    [Vue.js devtools - 安装方式 - 推荐](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd?hl=zh-CN)

        过滤器
    概念:Vue.js 允许你自定义过滤器,**可被用作一些常见的文本格式化**。过滤器可以用在两个地方:**mustache 插值和 v-bind 表达式**。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符指示;
    // 过滤器的定义语法
    // Vue.filter('过滤器的名称', function(){})
    // 过滤器中的 function ,第一个参数,已经被规定死了,永远都是 过滤器 管道符前面 传递过来的数据
    Vue.filter('过滤器的名称', function (data) {
      return data + '123'
    })

    {{ msg | msgFormat('love', 'you') | test }}


        // 定义一个 Vue 全局的过滤器,名字叫做  msgFormat
    Vue.filter('msgFormat', function (msg, arg, arg2) {
        // 字符串的  replace 方法,第一个参数,除了可写一个 字符串之外,还可以定义一个正则
        return msg.replace(/单纯/g, arg + arg2)
    })
    Vue.filter('test', function (msg) {
        return msg + '========'
    })

    {{ item.ctime | dateFormat() }} 删除
        // 全局的过滤器, 进行时间的格式化
        // 所谓的全局过滤器,就是所有的VM实例都共享的
    Vue.filter('dateFormat', function (dateStr, pattern = "") {
        // 根据给定的时间字符串,得到特定的时间
        var dt = new Date(dateStr)
        //   yyyy-mm-dd
        var y = dt.getFullYear()
        var m = dt.getMonth() + 1
        var d = dt.getDate()
    if (pattern.toLowerCase() === 'yyyy-mm-dd') {
        return `${y}-${m}-${d}`
    } else {
        var hh = dt.getHours()
        var mm = dt.getMinutes()
        var ss = dt.getSeconds()
        return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
    }
    })

        私有过滤器
    1. HTML元素:
    {{item.ctime | dataFormat('yyyy-mm-dd')}}
    2. 私有 `filters` 定义方式:
    filters: { // 私有局部过滤器,只能在 当前 VM 对象所控制的 View 区域进行使用  过滤器有两个 条件  【过滤器名称 和 处理函数】
        // 过滤器调用的时候,采用的是就近原则,如果私有过滤器和全局过滤器名称一致了,这时候 优先调用私有过滤器
        dataFormat(input, pattern = "") { // 在参数列表中 通过 pattern="" 来指定形参默认值,防止报错
          var dt = new Date(input);
          var y = dt.getFullYear();// 获取年月日
          var m = (dt.getMonth() + 1).toString().padStart(2, '0');
          var d = dt.getDate().toString().padStart(2, '0');
          // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日  否则,就返回  年-月-日 时:分:秒
          if (pattern.toLowerCase() === 'yyyy-mm-dd') {
            return `${y}-${m}-${d}`;
          } else {// 获取时分秒
            var hh = dt.getHours().toString().padStart(2, '0');
            var mm = dt.getMinutes().toString().padStart(2, '0');
            var ss = dt.getSeconds().toString().padStart(2, '0');
            return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
          }
        }
      }
    > 使用ES6中的字符串新方法 String.prototype.padStart(maxLength, fillString='') 或 String.prototype.padEnd(maxLength, fillString='')来填充字符串;

        全局过滤器
    // 定义一个全局过滤器
    Vue.filter('dataFormat', function (input, pattern = '') {
      var dt = new Date(input);
      var y = dt.getFullYear();// 获取年月日
      var m = (dt.getMonth() + 1).toString().padStart(2, '0');
      var d = dt.getDate().toString().padStart(2, '0');
      // 如果 传递进来的字符串类型,转为小写之后,等于 yyyy-mm-dd,那么就返回 年-月-日   否则,就返回  年-月-日 时:分:秒
      if (pattern.toLowerCase() === 'yyyy-mm-dd') {
        return `${y}-${m}-${d}`;
      } else {// 获取时分秒
        var hh = dt.getHours().toString().padStart(2, '0');
        var mm = dt.getMinutes().toString().padStart(2, '0');
        var ss = dt.getSeconds().toString().padStart(2, '0');
        return `${y}-${m}-${d} ${hh}:${mm}:${ss}`;
      }
    });
    > 注意:当有局部和全局两个名称相同的过滤器时候,会以就近原则进行调用,即:局部过滤器优先于全局过滤器被调用!

        键盘修饰符以及自定义键盘修饰符
    1.x中自定义键盘修饰符【了解即可】
    Vue.directive('on').keyCodes.f2 = 113;
    2.x中自定义键盘修饰符](https://cn.vuejs.org/v2/guide/events.html#键值修饰符)
    1. 通过`Vue.config.keyCodes.名称 = 按键值`来自定义案件修饰符的别名:
    Vue.config.keyCodes.f2 = 113;
    2. 使用自定义的按键修饰符:

        [自定义指令](https://cn.vuejs.org/v2/guide/custom-directive.html)
    1. 自定义全局和局部的 自定义指令:
        // 自定义全局指令 v-focus,为绑定的元素自动获取焦点:

        Vue.directive('focus', {
          inserted: function (el) { // inserted 表示被绑定元素插入父节点时调用
            el.focus();
          }
        });

    使用  Vue.directive() 定义全局的指令  v-focus
    // 其中:参数1 : 指令的名称,注意,在定义的时候,指令的名称前面,不需要加 v- 前缀, 但是: 在调用的时候,必须 在指令名称前 加上 v- 前缀来进行调用
    //  参数2: 是一个对象,这个对象身上,有一些指令相关的函数,这些函数可以在特定的阶段,执行相关的操作
    Vue.directive('focus', {
        bind: function (el) { // 每当指令绑定到元素上的时候,会立即执行这个 bind 函数,只执行一次
        // 注意: 在每个 函数中,第一个参数,永远是 el ,表示 被绑定了指令的那个元素,这个 el 参数,是一个原生的JS对象
        // 在元素 刚绑定了指令的时候,还没有 插入到 DOM中去,这时候,调用 focus 方法没有作用,  因为,一个元素,只有插入DOM之后,才能获取焦点
        // el.focus()
    },
        inserted: function (el) {  // inserted 表示元素 插入到DOM中的时候,会执行 inserted 函数【触发1次】
        el.focus()  // 和JS行为有关的操作,最好在 inserted 中去执行,放置 JS行为不生效
    },
        updated: function (el) {  // 当VNode更新的时候,会执行 updated, 可能会触发多次
    }
    })

        // 自定义一个 设置字体颜色的 指令

    Vue.directive('color', {
        // 样式,只要通过指令绑定给了元素,不管这个元素有没有被插入到页面中去,这个元素肯定有了一个内联的样式,  将来元素肯定会显示到页面中,这时候,浏览器的渲染引擎必然会解析样式,应用给这个元素
        bind: function (el, binding) {    // 和样式相关的操作,一般都可以在 bind 执行
        // el.style.color = 'red'
        // console.log(binding.name)  //color
        // console.log(binding.value)  // blue
        // console.log(binding.expression)  // 'blue'
        el.style.color = binding.value
        }
    })

        // 自定义局部指令 v-color 和 v-font-weight,为绑定的元素设置指定的字体颜色 和 字体粗细:
    directives: {
        color: { // 为元素设置指定的字体颜色
              bind(el, binding) {
                el.style.color = binding.value;
              }
          },
        'font-weight': function (el, binding2) { // 自定义指令的简写形式,等同于定义了 bind 和 update 两个钩子函数
              el.style.fontWeight = binding2.value;
            }
          }
    2. 自定义指令的使用方式:

         Vue 1.x 中 自定义元素指令【已废弃,了解即可】
    Vue.elementDirective('red-color', {
      bind: function () {
        this.el.style.color = 'red';
      }
    });
    使用方式:
    1232

         [vue实例的生命周期](https://cn.vuejs.org/v2/guide/instance.html#实例生命周期)
    什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
    [生命周期钩子](https://cn.vuejs.org/v2/api/#选项-生命周期钩子):就是生命周期事件的别名而已;
        生命周期钩子 = 生命周期函数 = 生命周期事件
    主要的生命周期函数分类:
    vue -- 初级(一)_第1张图片
        创建期间的生命周期函数:
    beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性
    created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板
    beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中
    mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
        运行期间的生命周期函数:
    beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点
    updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
        销毁期间的生命周期函数:
    beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
    destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

         [vue-resource 实现 get, post, jsonp请求](https://github.com/pagekit/vue-resource)
    除了 vue-resource 之外,还可以使用 `axios` 的第三方包实现实现数据的请求
    1. 之前的学习中,如何发起数据请求?
    2. 常见的数据请求类型?  get  post jsonp
    3. 测试的URL请求资源地址:
        get请求地址: http://vue.studyit.io/api/getlunbo
        post请求地址:http://vue.studyit.io/api/post
        jsonp请求地址:http://vue.studyit.io/api/jsonp
        4. JSONP的实现原理
    由于浏览器的安全性限制,不允许AJAX访问 协议不同、域名不同、端口号不同的 数据接口,浏览器认为这种访问不安全;
    可以通过动态创建script标签的形式,把script标签的src属性,指向数据接口的地址,因为script标签不存在跨域限制,这种数据获取方式,称作JSONP(注意:根据JSONP的实现原理,知晓,JSONP只支持Get请求);
    具体实现过程:
        先在客户端定义一个回调方法,预定义对数据的操作;
        再把这个回调方法的名称,通过URL传参的形式,提交到服务器的数据接口;
        服务器数据接口组织好要发送给客户端的数据,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行;
        客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能够拿到JSONP的数据了;
    带大家通过 Node.js ,来手动实现一个JSONP的请求例子;
        const http = require('http');
        // 导入解析 URL 地址的核心模块
        const urlModule = require('url');
        const server = http.createServer();
        // 监听 服务器的 request 请求事件,处理每个请求
        server.on('request', (req, res) => {
          const url = req.url;
          // 解析客户端请求的URL地址
          var info = urlModule.parse(url, true);
          // 如果请求的 URL 地址是 /getjsonp ,则表示要获取JSONP类型的数据
          if (info.pathname === '/getjsonp') {
            // 获取客户端指定的回调函数的名称
            var cbName = info.query.callback;
            // 手动拼接要返回给客户端的数据对象
            var data = {
              name: 'zs',
              age: 22,
              gender: '男',
              hobby: ['吃饭', '睡觉', '运动']
            }
            // 拼接出一个方法的调用,在调用这个方法的时候,把要发送给客户端的数据,序列化为字符串,作为参数传递给这个调用的方法:
            var result = `${cbName}(${JSON.stringify(data)})`;
            // 将拼接好的方法的调用,返回给客户端去解析执行
            res.end(result);
          } else {
            res.end('404');
          }
        });
        server.listen(3000, () => {
          console.log('server running at http://127.0.0.1:3000');
        });
    案例:
       


    const http = require('http')  // 导入 http 内置模块
    const urlModule = require('url')   // 这个核心模块,能够帮我们解析 URL地址,从而拿到  pathname  query
    // 创建一个 http 服务器
    const server = http.createServer()
    // 监听 http 服务器的 request 请求
    server.on('request', function (req, res) {
    const { pathname: url, query } = urlModule.parse(req.url, true)
    if (url === '/getscript') {
        var data = {
            name: 'xjj',
            age: 18,
            gender: '女孩子'
        }
        var scriptStr = `${query.callback}(${JSON.stringify(data)})`
        // res.end 发送给 客户端, 客户端去把 这个 字符串,当作JS代码去解析执行
        res.end(scriptStr)
    } else {
        res.end('404')
    }
    })
    // 指定端口号并启动服务器监听
    server.listen(3000, function () {
    console.log('server listen at http://127.0.0.1:3000')
    })

    5. vue-resource 的配置步骤:
    直接在页面中,通过`script`标签,引入 `vue-resource` 的脚本文件;
    注意:引用的先后顺序是:先引用 `Vue` 的脚本文件,再引用 `vue-resource` 的脚本文件;
    6. 发送get请求:
    getInfo() { // get 方式获取数据
      this.$http.get('http://127.0.0.1:8899/api/getlunbo').then(res => {
        console.log(res.body);
      })
    }
    7. 发送post请求:
    postInfo() {
      var url = 'http://127.0.0.1:8899/api/post';
      // post 方法接收三个参数:
      // 参数1: 要请求的URL地址
      // 参数2: 要发送的数据对象
      // 参数3: 指定post提交的编码类型为 application/x-www-form-urlencoded
      this.$http.post(url, { name: 'zs' }, { emulateJSON: true }).then(res => {
        console.log(res.body);
      });
    }
    8. 发送JSONP请求获取数据:
    jsonpInfo() { // JSONP形式从服务器获取数据
      var url = 'http://127.0.0.1:8899/api/jsonp';
      this.$http.jsonp(url).then(res => {
        console.log(res.body);
      });
    }

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

    // 如果我们通过全局配置了,请求的数据接口 根域名,则 ,在每次单独发起 http 请求的时候,请求的 url 路径,应该以相对路径开头,前面不能带 /  ,否则 不会启用根路径做拼接;
    Vue.http.options.root = 'http://vue.studyit.io/';
    // 全局启用 emulateJSON 选项
    Vue.http.options.emulateJSON = true;
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
        el: '#app',
        data: {
            name: '',
            list: [ // 存放所有品牌列表的数组 ]
        },
    created() { // 当 vm 实例 的 data 和 methods 初始化完毕后,vm实例会自动执行created 这个生命周期函数
        this.getAllList()
    },
    methods: {
    getAllList() { // 获取列表
        this.$http.get('api/getprodlist').then(result => {
            var result = result.body
            if (result.status === 0) { this.list = result.message } else { alert('获取数据失败!') }
        })
    },
    add() {  // 添加列表到后台服务器
        2. this.$http.post() 中接收三个参数:
            2.1 第一个参数: 要请求的URL地址
            2.2 第二个参数: 要提交给服务器的数据 ,要以对象形式提交给服务器 { name: this.name }
            3.3 第三个参数: 是一个配置对象,要以哪种表单数据类型提交过去, { emulateJSON: true }, 以普通表单格式,将数据提交给服务器 application/x-www-form-urlencoded
        3. 在 post 方法中,使用 .then 来设置成功的回调函数,如果想要拿到成功的结果,需要 result.body
    this.$http.post('api/addproduct', { name: this.name }).then(result => {
        if (result.body.status === 0) {
            this.getAllList()     // 添加完成后,需要手动,再调用一下 getAllList 刷新品牌列表
            this.name = ''        // 清空 name
        } else { alert('添加失败!') }
    })
    },
    del(id) { // 删除品牌
        this.$http.get('api/delproduct/' + id).then(result => {
            if (result.body.status === 0) { // 删除成功
            this.getAllList()
            } else { alert('删除失败!') }
        })
        }
    }
    });

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


       
       
       
       
    动画哦

       


    2. VM 实例:
    // 创建 Vue 实例,得到 ViewModel
        var vm = new Vue({
        el: '#app',
        data: {
            isshow: false
        },
        methods: {
        myAnimate() {
        this.isshow = !this.isshow;
        }
        }
        });
    3. 定义两组类样式:
        /* 定义进入和离开时候的过渡状态 */
        .fade-enter-active,
        .fade-leave-active {
            transition: all 0.2s ease;
            position: absolute;
        }
    /* v-enter 【这是一个时间点】 是进入之前,元素的起始状态,此时还没有开始进入 */
    /* v-leave-to 【这是一个时间点】 是动画离开之后,离开的终止状态,此时,元素 动画已经结束了 */
        /* 定义进入过渡的开始状态 和 离开过渡的结束状态 */
        .fade-enter,
        .fade-leave-to {
            opacity: 0;
            transform: translateX(100px);
        }

        [使用第三方 CSS 动画库](https://cn.vuejs.org/v2/guide/transitions.html#自定义过渡类名)
    1. 导入动画类库:
       
    2. 定义 transition 及属性:
            enter-active-class="fadeInRight"
        leave-active-class="fadeOutRight"
        :duration="{ enter: 500, leave: 800 }">
       

    动画

       

         使用动画钩子函数
    1. 定义 transition 组件以及三个钩子函数:


       
            @before-enter="beforeEnter"
        @enter="enter"
        @after-enter="afterEnter">
       
    OK

       

    2. 定义三个 methods 钩子方法:
    methods: {// 动画钩子函数的第一个参数:el,表示 要执行动画的那个DOM元素,是个原生的 JS DOM对象
        beforeEnter(el) { // 动画进入之前的回调
            el.style.transform = 'translateX(500px)';
        },
        enter(el, done) { // 动画进入完成时候的回调
            el.offsetWidth;// 这句话,没有实际的作用,但是,如果不写,出不来动画效果; 可以认为 el.offsetWidth 会强制动画刷新
            el.style.transform = 'translateX(0px)';
            el.style.transition = 'all 1s ease'
        //回调函数done是必须的
            done();  // 这里的 done, 起始就是 afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用
        },
        afterEnter(el) { // 动画进入完成之后的回调
            this.isshow = !this.isshow;
        }
    }
    3. 定义动画过渡时长和样式:
    .show{
        transition: all 0.4s ease;
        }

         [v-for 的列表过渡](https://cn.vuejs.org/v2/guide/transitions.html#列表的进入和离开过渡)
    1. 定义过渡样式:
       
    2. 定义DOM结构,其中,需要使用 transition-group 组件把v-for循环的列表包裹起来:
       


       


       
       
  • {{item}}

  •    

       

    3. 定义 VM中的结构:
        // 创建 Vue 实例,得到 ViewModel
        var vm = new Vue({
        el: '#app',
        data: {
        txt: '',
        list: [1, 2, 3, 4]
        },
        methods: {
        add() {
            this.list.push(this.txt);
            this.txt = '';
        }
        },
        del(i) {
            this.list.splice(i, 1)
        }
        });
    列表的排序过渡
    `` 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 `v-move` 特性,它会在元素的改变定位的过程中应用。
    `v-move` 和 `v-leave-active` 结合使用,能够让列表的过渡更加平缓柔和:
        .v-move{
        transition: all 0.8s ease;
        }
        .v-leave-active{
        position: absolute;
        }
    相关文章
    1. [vue.js 1.x 文档](https://v1-cn.vuejs.org/)
    2. [vue.js 2.x 文档](https://cn.vuejs.org/)
    3. [String.prototype.padStart(maxLength, fillString)](http://www.css88.com/archives/7715)
    4. [js 里面的键盘事件对应的键码](http://www.cnblogs.com/wuhua1/p/6686237.html)
    5. [pagekit/vue-resource](https://github.com/pagekit/vue-resource)
    6. [navicat如何导入sql文件和导出sql文件](https://jingyan.baidu.com/article/a65957f4976aad24e67f9b9b.html)
    7. [贝塞尔在线生成器](http://cubic-bezier.com/#.4,-0.3,1,.33)

         定义Vue组件
    什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可;
        组件化和模块化的不同:
    模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;
    组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;
         全局组件定义的三种方式
        // 如果使用 Vue.component 定义全局组件的时候,组件名称使用了 驼峰命名,则在引用组件的时候,需要把 大写的驼峰改为小写的字母,同时,两个单词之前,使用 - 链接; 如果不使用驼峰,则直接拿名称来使用即可;
        // 注意:不论是哪种方式创建出来的组件,组件的 template 属性指向的模板内容,必须有且只能有唯一的一个根元素
    1. 使用 Vue.extend 配合 Vue.component 方法:
        var login = Vue.extend({
        template: '

    登录

    '  // 通过 template 属性,指定了组件要展示的HTML结构
        });
        Vue.component('login', login);
    2. 直接使用 Vue.component 方法:
        Vue.component('register', {
        template: '

    注册

    '
        });

       
        Vue.component('mycom3', {
                template: '#tmpl'
            })
    3. 将模板字符串,定义到script标签种:
       
        同时,需要使用 Vue.component 来定义组件:
        Vue.component('account', {
        template: '#tmpl'
        });
        > 注意: 组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!

         组件中展示数据和响应事件
    1. 在组件中,`data`需要被定义为一个方法,例如:
        // 1. 组件可以有自己的 data 数据
        // 2. 组件的 data 和 实例的 data 有点不一样,实例中的 data 可以为一个对象,但是 组件中的 data 必须是一个方法
        // 3. 组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行;
    Vue.component('account', {
        template: '#tmpl',
        data() {
            return {
                msg: '大家好!'
            }
        },
        methods:{
            login(){
                alert('点击了登录按钮');
            }
        }
        });

    2. 在子组件中,如果将模板字符串,定义到了script标签中,那么,要访问子组件身上的`data`属性中的值,需要使用`this`来访问;
         【重点】为什么组件中的data属性必须定义为一个方法并返回一个对象
        1. 通过计数器案例演示
       
            var dataObj = { count: 0 }
            // 这是一个计数器的组件, 身上有个按钮,每当点击按钮,让 data 中的 count 值 +1
            Vue.component('counter', {
                template: '#tmpl',
                data: function () {
                    // return dataObj
                    return { count: 0 }
                },
                methods: {
                    increment() {
                        this.count++
                    }
                }
            })

         使用`components`属性定义局部子组件
        1. 组件实例定义方式:
       
        2. 引用组件:
       


           
       

         使用`flag`标识符结合`v-if`和`v-else`切换组件
    1. 页面结构:
       


           
           
           
       

    2. Vue实例定义:
       

         使用`:is`属性来切换不同的子组件,并添加切换动画
    1. 组件实例定义方式:
        // 登录组件
        const login = Vue.extend({
        template: `


           

    登录组件


       
    `
        });
        Vue.component('login', login);
        // 注册组件
        const register = Vue.extend({
        template: `

           

    注册组件


       
    `
        });
        Vue.component('register', register);
        // 创建 Vue 实例,得到 ViewModel
        var vm = new Vue({
        el: '#app',
        data: { comName: 'login' },
        methods: {}
        });
    2. 使用`component`标签,来引用组件,并通过`:is`属性来指定要加载的组件:
       

            登录
            注册
           

                 
                 
           

       

    3. 添加切换样式:
       

        父组件向子组件传值
    1. 组件实例定义方式,注意:一定要使用`props`属性来定义父组件传递过来的数据
            // 创建 Vue 实例,得到 ViewModel
            var vm = new Vue({
                el: '#app',
                data: {// 注意: 子组件中的 data 数据是子组件自身私有的,比如: 子组件通过 Ajax ,请求回来的数据,都可以放到 data 身上;data 上的数据,都是可读可写的;
                    msg: '这是父组件中的消息'
                },
                components: {
                    son: {
                        template: '

    这是子组件 --- {{finfo}}

    ',
                        // 注意: 组件中的 所有 props 中的数据,都是通过 父组件传递给子组件的,  props 中的数据,都是只读的,无法重新赋值
                        props: ['finfo']
                    }
                }
            });
        2. 使用`v-bind`或简化指令,将数据传递到子组件中:
       

           
       

         子组件向父组件传值
    1. 原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去;
    2. 父组件将方法的引用传递给子组件,其中,`getMsg`是父组件中`methods`中定义的方法名称,`func`是子组件调用传递过来方法时候的方法名称
       
    3. 子组件内部通过`this.$emit('方法名', 要传递的数据)`方式,来调用父组件中的方法,同时把数据传递给父组件使用
       


           
           
           
           
       

       

         评论列表案例

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


           

               
               
               

    这是一个大大的H1


               

               
               
           

       

       

         什么是路由?
    1. 后端路由:对于普通的网站,所有的超链接都是URL地址,所有的URL地址都对应服务器上对应的资源;
    2. 前端路由:对于单页面应用程序来说,主要通过URL中的hash(#号)来实现不同页面之间的切换,同时,hash有一个特点:HTTP请求中不会包含hash相关的内容;所以,单页面程序中的页面跳转主要用hash实现;
    3. 在单页面应用程序中,这种通过hash改变来切换页面的方式,称作前端路由(区别于后端路由);

         在 vue 中使用 vue-router
    1. 导入 vue-router 组件类库:
       
       
    2. 使用 router-link 组件来导航
       
        登录
        注册
    3. 使用 router-view 组件来显示匹配到的组件
       
       
    4. 创建使用`Vue.extend`创建组件
        // 4.1 使用 Vue.extend 来创建登录组件
        var login = Vue.extend({
        template: '

    登录组件

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

    注册组件

    '
        });
    5. 创建一个路由 router 实例,通过 routers 属性来定义路由匹配规则
        // 5. 创建一个路由 router 实例,通过 routers 属性来定义路由匹配规则
        // 2. 创建一个路由对象, 当 导入 vue-router 包之后,在 window 全局对象中,就有了一个 路由的构造函数,叫做 VueRouter
        var router = new VueRouter({
        routes: [
        { path: '/', redirect: '/login' },
        { path: '/login', component: login },// 注意: component 的属性值,必须是一个 组件的模板对象, 不能是 组件的引用名称;
        { path: '/register', component: register }
        ],
        linkActiveClass: 'myactive'   //设置路由高亮
        });
    6. 使用 router 属性来使用路由规则
        // 6. 创建 Vue 实例,得到 ViewModel
        var vm = new Vue({
        el: '#app',
        router: router // 使用 router 属性来使用路由规则
        });

       
        登录
       
            var login = {
                template: '

    登录 --- {{ $route.query.id }} --- {{ $route.query.name }}

    ',
                created(){ // 组件的生命周期钩子函数
                    // console.log(this.$route)
                    // console.log(this.$route.query.id)
                }
            }
            var router = new VueRouter({
                routes: [
                    { path: '/login', component: login },
                ]
            })

         在路由规则中定义参数
    1. 在规则中定义参数:
        { path: '/register/:id', component: register }
    2. 通过 `this.$route.params`来获取路由中的参数:
        var register = Vue.extend({
        template: '

    注册组件 --- {{this.$route.params.id}}

    '
        });
        登录
       
            var login = {
                template: '

    登录 --- {{ $route.params.id }} --- {{ $route.params.name }}

    ',
                created(){ // 组件的生命周期钩子函数
                    console.log(this.$route.params.id)
                }
            }
            var router = new VueRouter({
                routes: [
                    { path: '/login/:id/:name', component: login },
                ]
            })

         使用 `children` 属性实现路由嵌套
       


            Account
           
       

       

         命名视图实现经典布局
    1. 标签代码结构:
       


           
           

               
               
           

       

    2. JS代码:
       
        3. CSS 样式:
       

         `watch`属性的使用
    考虑一个问题:想要实现 `名` 和 `姓` 两个文本框的内容改变,则全名的文本框中的值也跟着改变;(用以前的知识如何实现???)
        1. 监听`data`中属性的改变:
       


            +
            =
            {{fullName}}
       

       
    2. 监听路由对象的改变:
       

            登录
            注册
           
       

       

         `computed`计算属性的使用
    1. 默认只有`getter`的计算属性:
       


            +
            =
            {{fullName}}
       

       
        2. 定义有`getter`和`setter`的计算属性:
       


           
           
           
           
            {{fullName}}
       

       

         `watch`、`computed`和`methods`之间的对比
    1. `computed`属性的结果会被缓存,除非依赖的响应式属性变化才会重新计算。主要当作属性来使用;
    2. `methods`方法表示一个具体的操作,主要书写业务逻辑;
    3. `watch`一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;可以看作是`computed`和`methods`的结合体;

         `nrm`的安装使用
    作用:提供了一些最常用的NPM包镜像地址,能够让我们快速的切换安装包时候的服务器地址;
    什么是镜像:原来包刚一开始是只存在于国外的NPM服务器,但是由于网络原因,经常访问不到,这时候,我们可以在国内,创建一个和官网完全一样的NPM服务器,只不过,数据都是从人家那里拿过来的,除此之外,使用方式完全一样;
        1. 运行`npm i nrm -g`全局安装`nrm`包;
        2. 使用`nrm ls`查看当前所有可用的镜像源地址以及当前所使用的镜像源地址;
        3. 使用`nrm use npm`或`nrm use taobao`切换不同的镜像源地址;

        Webpack:
        在网页中会引用哪些常见的静态资源?
        + JS
        - .js  .jsx  .coffee  .ts(TypeScript  类 C# 语言)
        + CSS
        - .css  .less   .sass  .scss
        + Images
        - .jpg   .png   .gif   .bmp   .svg
        + 字体文件(Fonts)
        - .svg   .ttf   .eot   .woff   .woff2
        + 模板文件
        - .ejs   .jade  .vue【这是在webpack中定义组件的方式,推荐这么用】

         网页中引入的静态资源多了以后有什么问题???
    1. 网页加载速度慢, 因为 我们要发起很多的二次请求;
    2. 要处理错综复杂的依赖关系

         如何解决上述两个问题
    1. 合并、压缩、精灵图、图片的Base64编码
    2. 可以使用之前学过的requireJS、也可以使用webpack可以解决各个包之间的复杂依赖关系;

         什么是webpack?
    webpack 是前端的一个项目构建工具,它是基于 Node.js 开发出来的一个前端工具;

         如何完美实现上述的2种解决方案
        1. 使用Gulp, 是基于 task 任务的;
        2. 使用Webpack, 是基于整个项目进行构建的;
        + 借助于webpack这个前端自动化构建工具,可以完美实现资源的合并、打包、压缩、混淆等诸多功能。
        + 根据官网的图片介绍webpack打包的过程
        + [webpack官网](http://webpack.github.io/)

         webpack安装的两种方式
        1. 运行`npm i webpack -g`全局安装webpack,这样就能在全局使用webpack的命令
        2. 在项目根目录中运行`npm i webpack --save-dev`安装到项目依赖中

         初步使用webpack打包构建列表隔行变色案例
    1. 运行`npm init`初始化项目,使用npm管理项目中的依赖包
    2. 创建项目基本的目录结构
    3. 使用`cnpm i jquery --save`安装jquery类库
    4. 创建`main.js`并书写各行变色的代码逻辑:
        // 导入jquery类库
        import $ from 'jquery'
        $('#list li:even').css('backgroundColor','lightblue');    // 设置偶数行背景色,索引从0开始,0是偶数
        $('#list li:odd').css('backgroundColor','pink');    // 设置奇数行背景色
    5. 直接在页面上引用`main.js`会报错,因为浏览器不认识`import`这种高级的JS语法,需要使用webpack进行处理,webpack默认会把这种高级的语法转换为低级的浏览器能识别的语法;
    6. 运行`webpack 入口文件路径 输出文件路径`对`main.js`进行处理:
        webpack src/js/main.js dist/bundle.js

         使用webpack的配置文件简化打包时候的命令
    1. 在项目根目录中创建`webpack.config.js`
    2. 由于运行webpack命令的时候,webpack需要指定入口文件和输出文件的路径,所以,我们需要在`webpack.config.js`中配置这两个路径:
        // 导入处理路径的模块
        var path = require('path');
        // 导出一个配置对象,将来webpack在启动的时候,会默认来查找webpack.config.js,并读取这个文件中导出的配置对象,来进行打包处理
        module.exports = {
        entry: path.resolve(__dirname, 'src/js/main.js'), // 项目入口文件
        output: { // 配置输出选项
        path: path.resolve(__dirname, 'dist'), // 配置输出的路径
        filename: 'bundle.js' // 配置输出的文件名
        }
        }

         实现webpack的实时打包构建
    1. 由于每次重新修改代码之后,都需要手动运行webpack打包的命令,比较麻烦,所以使用`webpack-dev-server`来实现代码实时打包编译,当修改代码之后,会自动进行打包构建。
    2. 运行`cnpm i webpack-dev-server --save-dev`安装到开发依赖
    3. 安装完成之后,在命令行直接运行`webpack-dev-server`来进行打包,发现报错,此时需要借助于`package.json`文件中的指令,来进行运行`webpack-dev-server`命令,在`scripts`节点下新增`"dev": "webpack-dev-server"`指令,发现可以进行实时打包,但是dist目录下并没有生成`bundle.js`文件,这是因为`webpack-dev-server`将打包好的文件放在了内存中
        + 把`bundle.js`放在内存中的好处是:由于需要实时打包编译,所以放在内存中速度会非常快
        + 这个时候访问webpack-dev-server启动的`http://localhost:8080/`网站,发现是一个文件夹的面板,需要点击到src目录下,才能打开我们的index首页,此时引用不到bundle.js文件,需要修改index.html中script的src属性为:``
        + 为了能在访问`http://localhost:8080/`的时候直接访问到index首页,可以使用`--contentBase src`指令来修改dev指令,指定启动的根目录:
        "dev": "webpack-dev-server --contentBase src"
        同时修改index页面中script的src属性为``

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

         实现自动打开浏览器、热更新和配置浏览器的默认端口号
    **注意:热更新在JS中表现的不明显,可以从一会儿要讲到的CSS身上进行介绍说明!**
         方式1:
    修改`package.json`的script节点如下,其中`--open`表示自动打开浏览器,`--port 4321`表示打开的端口号为4321,`--hot`表示启用浏览器热更新:
        "dev": "webpack-dev-server --hot --port 4321 --open"
         方式2:
    1. 修改`webpack.config.js`文件,新增`devServer`节点如下:
        devServer:{
        hot:true,
        open:true,
        port:4321
        }
    2. 在头部引入`webpack`模块:
    var webpack = require('webpack');
    3. 在`plugins`节点下新增:
    new webpack.HotModuleReplacementPlugin()

         使用webpack打包css文件
    1. 运行`cnpm i style-loader css-loader --save-dev`
    2. 修改`webpack.config.js`这个配置文件:
        module: { // 用来配置第三方loader模块的
        rules: [ // 文件的匹配规则
        { test: /\.css$/, use: ['style-loader', 'css-loader'] }//处理css文件的规则
        ]
        }
    3. 注意:`use`表示使用哪些模块来处理`test`所匹配到的文件;`use`中相关loader模块的调用顺序是从后向前调用的;

         使用webpack打包less文件
    1. 运行`cnpm i less-loader less -D`
    2. 修改`webpack.config.js`这个配置文件:
        { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] },

         使用webpack打包sass文件
    1. 运行`cnpm i sass-loader node-sass --save-dev`
    2. 在`webpack.config.js`中添加处理sass文件的loader模块:
        { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }

         使用webpack处理css中的路径
    1. 运行`cnpm i url-loader file-loader --save-dev`
    2. 在`webpack.config.js`中添加处理url路径的loader模块:
        { test: /\.(png|jpg|gif)$/, use: 'url-loader' }
    3. 可以通过`limit`指定进行base64编码的图片大小;只有小于指定字节(byte)的图片才会进行base64编码:
    { test: /\.(png|jpg|gif)$/, use: 'url-loader?limit=43960' },

         使用babel处理高级JS语法
    1. 运行`cnpm i babel-core babel-loader babel-plugin-transform-runtime --save-dev`安装babel的相关loader包
    2. 运行`cnpm i babel-preset-es2015 babel-preset-stage-0 --save-dev`安装babel转换的语法
    3. 在`webpack.config.js`中添加相关loader模块,其中需要注意的是,一定要把`node_modules`文件夹添加到排除项:
        { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
    4. 在项目根目录中添加`.babelrc`文件,并修改这个配置文件如下:
        {
        "presets":["es2015", "stage-0"],
        "plugins":["transform-runtime"]
        }
    5. 注意:语法插件`babel-preset-es2015`可以更新为`babel-preset-env`,它包含了所有的ES相关的语法;**

    相关文章
    [babel-preset-env:你需要的唯一Babel插件](https://segmentfault.com/p/1210000008466178)
    [Runtime transform 运行时编译es6](https://segmentfault.com/a/1190000009065987)

        webpack.config.js:
        // 由于 webpack 是基于Node进行构建的,所有,webpack的配置文件中,任何合法的Node代码都是支持的
        var path = require('path')
        // 在内存中,根据指定的模板页面,生成一份内存中的首页,同时自动把打包好的bundle注入到页面底部
        // 如果要配置插件,需要在导出的对象中,挂载一个 plugins 节点
        var htmlWebpackPlugin = require('html-webpack-plugin')
        // 当以命令行形式运行 webpack 或 webpack-dev-server 的时候,工具会发现,我们并没有提供 要打包 的文件的 入口 和 出口文件,此时,他会检查项目根目录中的配置文件,并读取这个文件,就拿到了导出的这个 配置对象,然后根据这个对象,进行打包构建
        module.exports = {
        entry: path.join(__dirname, './src/main.js'), // 入口文件
        output: { // 指定输出选项
        path: path.join(__dirname, './dist'), // 输出路径
        filename: 'bundle.js' // 指定输出文件的名称
        },
        plugins: [ // 所有webpack  插件的配置节点
        new htmlWebpackPlugin({
        template: path.join(__dirname, './src/index.html'), // 指定模板文件路径
        filename: 'index.html' // 设置生成的内存页面的名称
        })
        ],
        module: { // 配置所有第三方loader 模块的
        rules: [ // 第三方模块的匹配规则
        { test: /\.css$/, use: ['style-loader', 'css-loader'] }, // 处理 CSS 文件的 loader
        { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, // 处理 less 文件的 loader
        { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] }, // 处理 scss 文件的 loader
        { test: /\.(jpg|png|gif|bmp|jpeg)$/, use: 'url-loader?limit=7631&name=[hash:8]-[name].[ext]' }, // 处理 图片路径的 loader
        // limit 给定的值,是图片的大小,单位是 byte, 如果我们引用的 图片,大于或等于给定的 limit值,则不会被转为base64格式的字符串, 如果 图片小于给定的 limit 值,则会被转为 base64的字符串
        { test: /\.(ttf|eot|svg|woff|woff2)$/, use: 'url-loader' }, // 处理 字体文件的 loader
        { test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }, // 配置 Babel 来转换高级的ES语法
        ]
        }
        }

         在webpack中配置.vue组件页面的解析
    1. 运行`cnpm i vue -S`将vue安装为运行依赖;
    2. 运行`cnpm i vue-loader vue-template-compiler -D`将解析转换vue的包安装为开发依赖;
    3. 运行`cnpm i style-loader css-loader -D`将解析转换CSS的包安装为开发依赖,因为.vue文件中会写CSS样式;
    4. 在`webpack.config.js`中,添加如下`module`规则:
    module: {
        rules: [
        { test: /\.css$/, use: ['style-loader', 'css-loader'] },
        { test: /\.vue$/, use: 'vue-loader' }
        ]
        }
    5. 创建`App.js`组件页面:



    6. 创建`main.js`入口文件:
    // 导入 Vue 组件
    import Vue from 'vue'
    // 导入 App组件
        import App from './components/App.vue'
    // 创建一个 Vue 实例,使用 render 函数,渲染指定的组件
        var vm = new Vue({
        el: '#app',
        render: c => c(App)
        });

         在使用webpack构建的Vue项目中使用模板对象?
    1. 在`webpack.config.js`中添加`resolve`属性:
    resolve: {
        alias: {
        'vue$': 'vue/dist/vue.esm.js'
        }
        }

         ES6中语法使用总结
    1. 使用 `export default` 和 `export` 导出模块中的成员; 对应ES5中的 `module.exports` 和 `export`
    2. 使用 `import ** from **` 和 `import '路径'` 还有 `import {a, b} from '模块标识'` 导入其他模块
    3. 使用箭头函数:`(a, b)=> { return a-b; }`
    // 注意: export default 向外暴露的成员,可以使用任意的变量来接收
    // 注意: 在一个模块中,export default 只允许向外暴露1次
    // 注意: 在一个模块中,可以同时使用 export default 和 export 向外暴露成员
    export var content = '哈哈哈'
    // 注意: 使用 export 向外暴露的成员,只能使用 { } 的形式来接收,这种形式,叫做 【按需导出】
    // 注意: export 可以向外暴露多个成员, 同时,如果某些成员,我们在 import 的时候,不需要,则可以 不在 {}  中定义
    // 注意: 使用 export 导出的成员,必须严格按照 导出时候的名称,来使用  {}  按需接收;
    // 注意: 使用 export 导出的成员,如果 就想 换个 名称来接收,可以使用 as 来起别名;

        在vue组件页面中,集成vue-router路由模块
        [vue-router官网](https://router.vuejs.org/)
    1. 导入路由模块:
        import VueRouter from 'vue-router'
    2. 安装路由模块:
        Vue.use(VueRouter);
    3. 导入需要展示的组件:
        import login from './components/account/login.vue'
        import register from './components/account/register.vue'
    4. 创建路由对象:
        var router = new VueRouter({
        routes: [
        { path: '/', redirect: '/login' },
        { path: '/login', component: login },
        { path: '/register', component: register }
        ]
        });
    5. 将路由对象,挂载到 Vue 实例上:
        var vm = new Vue({
        el: '#app',
        // render: c => { return c(App) }
        render(c) {
        return c(App);
        },
        router // 将路由对象,挂载到 Vue 实例上
        });
    6. 改造App.vue组件,在 template 中,添加`router-link`和`router-view`:
        登录
        注册
       

         组件中的css作用域问题

     

    你可能感兴趣的:(vue)