Vue

140 阅读7分钟

起步

参考[:](Vue.js 2.0 快速上手精华梳理 - 掘金 (juejin.cn))

建议Vue 2.0 的学习顺序

  1. 扎实的 JavaScript / HTML / CSS 基本功。这是前置条件。
  2. 通读官方教程 (guide) 的基础篇。不要用任何构建工具,就只用最简单的 script,把教程里的例子模仿一遍,理解用法。不推荐上来就直接用 vue-cli 构建项目,尤其是如果没有 Node/Webpack 基础。
  3. 照着官网上的示例,自己想一些类似的例子,模仿着实现来练手,加深理解。
  4. 阅读官方教程进阶篇的前半部分,到『自定义指令 (Custom Directive) 』为止。着重理解 Vue 的响应式机制和组件生命周期。『渲染函数(Render Function)』如果理解吃力可以先跳过。
  5. 阅读教程里关于路由和状态管理的章节,然后根据需要学习 vue-router 和 vuex。同样的,先不要管构建工具,以跟着文档里的例子理解用法为主。
  6. 走完基础文档后,如果你对于基于 Node 的前端工程化不熟悉,就需要补课了。下面这些严格来说并不是 Vue 本身的内容,也不涵盖所有的前端工程化知识,但对于大型的 Vue 工程是前置条件,也是合格的『前端工程师』应当具备的知识。

前端生态/工程化

  1. 了解 JavaScript 背后的规范,ECMAScript 的历史和目前的规范制定方式。学习 ES2015/16 的新特性,理解 ES2015 modules,适当关注还未成为标准的提案。
  2. 学习命令行的使用。建议用 Mac。
  3. 学习 Node.js 基础。建议使用 nvm 这样的工具来管理机器上的 Node 版本,并且将 npm 的 registry 注册表配置为淘宝的镜像源。至少要了解 npm 的常用命令,npm scripts 如何使用,语义化版本号规则,CommonJS 模块规范(了解它和 ES2015 Modules 的异同),Node 包的解析规则,以及 Node 的常用 API。应当做到可以自己写一些基本的命令行程序。注意最新版本的 Node (6+) 已经支持绝大部分 ES2015 的特性,可以借此巩固 ES2015。
  4. 了解如何使用 / 配置 Babel 来将 ES2015 编译到 ES5 用于浏览器环境。
  5. 学习 Webpack。Webpack 是一个极其强大同时也复杂的工具,作为起步,理解它的『一切皆模块』的思想,并基本了解其常用配置选项和 loader 的概念/使用方法即可,比如如何搭配 Webpack 使用 Babel。学习 Webpack 的一个挑战在于其本身文档的混乱,建议多搜索搜索,应该还是有质量不错的第三方教程的。英文好的建议阅读 Webpack 2.0 的文档,比起 1.0 有极大的改善,但需要注意和 1.0 的不兼容之处。

Vue 进阶

  1. 有了 Node 和 Webpack 的基础,可以通过 vue-cli 来搭建基于 Webpack ,并且支持单文件组件的项目了。建议用 webpack-simple 这个模板开始,并阅读官方教程进阶篇剩余的内容以及 vue-loader 的文档,了解一些进阶配置。有兴趣的可以自己亲手从零开始搭一个项目加深理解。
  2. 根据 例子 尝试在 Webpack 模板基础上整合 vue-router 和 vuex
  3. 深入理解 Virtual DOM 和『渲染函数 (Render Functions)』这一章节(可选择性使用 JSX),理解模板和渲染函数之间的对应关系,了解其使用方法和适用场景。
  4. (可选)根据需求,了解服务端渲染的使用(需要配合 Node 服务器开发的知识)。其实更重要的是理解它所解决的问题并搞清楚你是否需要它。
  5. 阅读开源的 Vue 应用、组件、插件源码,自己尝试编写开源的 Vue 组件、插件。

1. 什么是vue

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的框架。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。

2. Vue基础语法知识

2.1 Vue是怎么工作的

新建index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>学习Vue</title>
</head>
<body>
    <!-- 2. Vue 挂载点 - Vue 的虚拟 DOM 在这里操作到实际渲染 -->
    <div id="app"></div>
    <!-- 1. 引用 Vue -->
    <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    <!-- Vue Router CDN - 管理路由 -->
    <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.js"></script>
    <!-- Axios CDN - 调用接口 --> 
    <script src="https://cdn.bootcss.com/axios/0.18.0/axios.js"></script>
    <script>
        new Vue({
            // 3. el - 挂载目标,即渲染在哪个挂载点
            el:"#app",
           data() { 
               return { 
                   text: 'Hello World!'
               } 
           }
        });

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

2.2 el优化

el 挂载形式,在 Vue 内部运行机制中,它会根据你传入的值,进行查找:

  • 如果传入的是 #app,那它就判断查找 idapp 的节点;
  • 如果传入的是 .app,那它就查找 classapp 的节点;
  • 如果传入的是节点名 div,那它就查找节点名……

大家应该清楚,这样判断查找是需要时间的,多执行一个判断都是罪恶。 所以我们可以:

el: document.getElementById('app'),

这般操作,使得 Vue 直接将挂载点挂载到 id 上去,从而获得更好的加载速度。这算是对 el 的一个小优化。

2.3 插值表达式

通过 {{}} 这个插值表达式的使用,对data其里面的数据进行操作。 下面,我们进一步讲解这个插值表达式 {{}} 还可以进行哪种骚操作:

  • 对象:{{ {name: 'jack'} }}
  • 字符串 {{ 'Hello World!' }}
  • 布尔值: {{ isTrue == -1 }}
  • 三元表达式: {{ isTrue ? '正确' : '错误' }}

2.4 指令 v-*

在 Vue 中,如果单单使用 {{}} 这种插值表达式,是满足不了我们对数据的操作欲望的。所以,Vue 以 v-ifv-bind 等形式,提供了一些对于页面 + 数据的更为方便的操作:指令

  • v-text
  • v-html
  • v-if
  • v-else-if
  • v-else
  • v-show
  • v-bind
  • v-on
  • v-model
  • v-for

2.5 methods

<body>
    <div id="app">
        <button v-on:click="addStyle">点我</button>
    </div>
<script>
    new Vue({
        el:"#app",
        data(){
            return{

            }
        },
        methods:{
            addStyle(e){
                console(成功添加样式)
            }
        }
    });

</script>
  1. 首先,在上面的 <button> 中,我们通过 @click 绑定了事件 addStyle

  2. 接着,方法的编写,需要写到与 data 同级的 methods 中:

methods:{
    addStyle(e){
        console(成功添加样式)
    }
}

2.6 组件component

组件是 Vue 学习的重点

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
        <my-head></my-head>
        <my-body></my-body>
        <my-foot></my-foot>
    </div>
<script>
    var Head={
        template:"<div>我是头</div>"
    };
    var Body={
        template:"<div>我是身体</div>"
    };
    var Foot={
        template:"<div>我是底部</div>"
    };
    new Vue({
        el:"#app",
        data(){
            return{

            }
        },
        methods:{
        },
        components:{
            "my-head":Head,
            "my-body":Body,
            "my-foot":Foot
        }
    });

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

2.7 父子组件通信

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
      <son :name="name"></son>
    </div>
<script>
    var Son={
        template:"<div>我是{{name}}</div>",
        props:["name"]

    };
    new Vue({
        el:"#app",
        data(){
            return{
                name:"皮皮虾"
            }
        },
        methods:{
        },
        components:{
            "son":Son
        }
    });

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

父组件中的数据,通过 v-bind:*** 的形式,将父组件中的 data,发送给子组件。而子组件呢,通过 props 的定义,获取到了父亲的数据。

2.7.1 共用组件

我们通过 Vue.component('组件名',{ }) 的形式,注册了个全局组件 beautiful-girl,这样,父子组件都可以直接调用该组件

2.8 过滤器filter

2.8.1 局部过滤器

在工作中,我们经常需要对一些后端传回来的数据进行过滤。例如:我司 Java 小哥传回来的金钱,就是分进制的,即:1元 = 100分。所以传回个 2000,其实是 20 元。那么,在 Vue 中,我们该如何对数据进行过滤呢?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
     我是钱多多,我有{{money}}分,{{money | yuan }}元
    </div>
<script>

    new Vue({
        el:"#app",
        data(){
            return{
                money:100000
            }
        },
        methods:{
        },
       filters:{
           yuan(val){
                return (val/100);
            }
       }
    });

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

在上面,我们通过 filters 中的 yuan 方法,对数据进行了过滤,将 money 的数据,从 100000 变成了 1000

2.8.2 全局过滤器

// 全局过滤器
Vue.filter('yuan', function(val)
{ 
    return (val/100);
})

3 监听数据

3.1 侦听属性

监听属性 watch,我们可以通过 watch 来响应数据的变化。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
        <input type="text" v-model="name" />
        {{name}}
    </div>
<script type="text/javascript">
    var vm=new Vue({
        el:"#app",
        data(){
            return{
                name:'jiankuaji'
            }
        },
        watch: {
            name (newVal,oldValue) {
                    alert(newVal);
                    alert(oldValue);
            }
        }
    });
</script>
</body>
</html>

3.2 计算属性computed

在上面,我们讲了通过 watch 来监听 datanumberstring 等字段的改变。但是,在 Vue 中,为了方便我们的监听操作,Vue 还定义了个方法:computed,我们可以通过 computed,监控我们在 data 中定义的全部数据。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
        {{name}}
        {{firstName}}
    </div>
<script type="text/javascript">
    var vm=new Vue({
        el:"#app",
        data(){
            return{
                name:'jiankuaji',
            }
        },
        computed:{
            firstName(){
                return this.name+"sd";
            }
        }
    });
</script>
</body>
</html>

3.3 watch、computed 与 methods 对比

  • computed 是根据 data 中的数据变化,而进行的操作。即 this.任意数据 改变了,那么,computed 就会进行改变;而如果 this.任务数据 不变,那么 computed 就会执行它的缓存策略,不会更新

  • methods 一般是根据点击之类的事件来触发的,例如用户通过 @click="方法" 来进行数据的改变。

  • watch 属性强调自身值的变化前后的动作。 watch 在处理异步操作或者开销较大的操作上有优势。

    • 执行异步操作不能串行返回结果,使用 watch
    • 开销较大的操作,避免堵塞主线程,使用 watch
    • 简单且串行返回的,使用 computed

4 用户输入

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
        <input v-model="name" replace="用户名称">
        单个多选框
        <input type="checkbox" v-model="checkbox">是否勾选


        多选框
        <input type="checkbox" v-model="checkboxs" value="j">j
        <input type="checkbox" v-model="checkboxs" value="i">i
        <input type="checkbox" v-model="checkboxs" value="a">a
        <input type="checkbox" v-model="checkboxs" value="n">n
        {{checkbox}}  {{checkboxs}}

        单选框
        <input type="radio" value="男" v-model="sex"><input type="radio" value="女" v-model="sex">女
        {{sex}}

        下拉框
        <select v-model="select">
            <option value="">选择一个网站</option>
            <option value="www.runoob.com">Runoob</option>
            <option value="www.google.com">Google</option>
        </select>
        我选择的是{{select}}
    </div>
<script type="text/javascript">
    var vm=new Vue({
        el:"#app",
        data:{
            name:'',
            checkbox:true,
            checkboxs:["j"],
            sex:'',
            select:""
        }
    });

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

5 生命周期

image.png

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<body>
    <div id="app">
        {{name}}
    </div>
<script type="text/javascript">
    var vm=new Vue({
        el:"#app",
        data(){
            return{
                name:'jiankuaji'   
            }
        },
        beforeCreate(){
            console.log("创建前")
        },
        created(){
            console.log("创建后")
        },
        
    });

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