20

一个后端开发的 Vue 笔记【入门级】

 3 years ago
source link: https://segmentfault.com/a/1190000023913009
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

bbeef49bf72e45ccbb24cc89f442d350~tplv-k3u1fbpfcp-zoom-1.image

一 前言

最近找了些教程,顺带着趴在官网上,看了看 Vue 的一些内容,入门的一些概念,以及基础语法,还有一些常用的操作,瞄了一眼,通篇文字+贴了部分代码 9000 多字,入门语法什么的还是很好理解的,以前也有一定做小程序的基础,感觉还是很相似的,不过对于一些稍复杂的点,感觉还是总结的不够细致,例如插槽,和计算属性等,平时前端的东西看的也不是很多,学习过程中整理的笔记,和大家一起分享交流!欢迎各位大大交流意见~

二 初始 Vue

(一) Vue 概念理解

(1) Vue.js 是什么

Vue (读音 /vjuː/,类似于 view ) 是一套用于构建用户界面的 渐进式框架 。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。

(2) 渐进式框架是什么

看了一些教程以及文章,简单理解的渐进式框架就三个字 【不强求】 ,Vue并不强求你用它的所有内容(功能特性),用户完全可以根据自己情况进行选择,使用其部分即可。

这一块某乎上有一个比较好的答案,很容易度娘到,贴了部分

vue即主张较少,也就是说可以在原有系统上面,引入vue直接就可以当jquery用,使用 vue,你可以在原有大系统的上面,把一两个组件改用它实现,当 jQuery 用;也可以整个用它全家桶开发

(二) MVVM 架构

正式学习 Vue 前我们首先还需要了解一个基于前端的架构模式,也就是 MVVM ,它是 Model-View-ViewMode 的简写,其关系简单的描述为下图:

6923ffab34e147d0a734dd7c15c79eaf~tplv-k3u1fbpfcp-zoom-1.image

  • Model(模型层):表示 Javascript 数据对象
  • View(视图层):表示 DOM,也可以简单理解为前端展示的内容
  • ViewModel:连接视图和数据,即用于双向绑定数据与页面

在 MVVM 架构中,视图和数据是没有办法直接进行沟通的,只能通过 ViewModel 来做一个中间关系, ViewModel 可以观察到数据的变化,然后更新视图内容,亦或者监听到视图的变化,并能通知数据发生改变

后面我马上会写一个入门的小案例,可以一起来体会一下它的特点!

(三) Vue 的优点

1、体积小

  • 压缩后33K

2、更高的运行效率

  • 基于虚拟dom一种可以预先通过 javascript 进行各种计算,把最终的 DOM操作计算出来并优化的技术,由于这个DOM操作属于预处理操作,并没有真实的操作DOM,所以 叫做虚拟DOM。

3、双向数据绑定

  • 让开发者不用再去操作 dom 对象,把更多的精力投入到业务逻辑上

4、生态丰富、学习成本低

  • 市场上拥有大量成熟、稳定的基于 vue.js 的 ui 框架、常用组件!
  • 拿来即用实现快速开发
  • 对初学者友好、入门容易、学习资料多

(四) 入门案例

编写 Vue 你可以选择使用 Vscode 、 HBuilder 、sublime、Webstrom、甚至 IDEA 都是可以的,自行选择就好了

首先我们需要引入 Vue,你可以去官网直接 down 下文件,进行一个本地的引入,类似引入 jQuery,或者使用一个网络的引用,例如下文中,在官网中就可以找到这种引入或下载的地址

可以看到,引入后,我们通过 new 的这种形式创建了一个 Vue 的实例,其中通过 el 找到 id 值为 hello 的 div 进行绑定,在 data 中进行一个赋值,而在div 中 通过两组大括号来对数据进行回显

如果你有一些微信小程序的基础的话,其实可以发现,这两者结构看起来似乎有一些相似的

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="hello">
  <h2>{{content}}</h2>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
  var vm = new Vue({
      el: "#hello",
      data:{
        content: "Hello Vue!"
      }
  })
</script>

</body>
</html>

回显数据肯定是没问题的,我们试着在控制台修改 content 的值,可以看到随之页面也就发生改变了

872d206596254eabbecc6a1ed01335da~tplv-k3u1fbpfcp-zoom-1.image

我们已经成功创建了第一个 Vue 应用!看起来这跟渲染一个字符串模板非常类似,但是 Vue 在背后做了大量工作。现在数据和 DOM 已经被建立了关联,所有东西都是 响应式的 。我们要怎么确认呢?打开你的浏览器的 JavaScript 控制台 (就在这个页面打开),并修改 app.message 的值,你将看到上例相应地更新。

注意我们不再和 HTML 直接交互了。一个 Vue 应用会将其挂载到一个 DOM 元素上 (对于这个例子是 #app ) 然后对其进行完全控制。那个 HTML 是我们的入口,但其余都会发生在新创建的 Vue 实例内部。—— Vue 官网

三 Vue 基本语法

(一) 声明式渲染

如果有接触过 Thymeleaf 这样的模板,你可以看出来,上面的 Vue 案例就是采用了一个简洁模板语法,即两组大括号包裹值,来声明式声明式地将数据渲染进 DOM 的系统,这其实和 Thymeleaf 中的 $ 加一组大括号 是相似的

我们还有一种绑定元素的方式:即使用指令

<div id="hello-2">
  <span v-bind:title="content">
    鼠标悬停几秒钟查看此处动态绑定的提示信息!
  </span>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
  var vm = new Vue({
      el: "#hello-2",
      data:{
        content: '页面加载于 ' + new Date().toLocaleString()
      }
  })
</script>

观察结果,我们将鼠标悬停在文字上方,被绑定的数据就会出现

8c6a68d539bd42d99953b8e912d1afbd~tplv-k3u1fbpfcp-zoom-1.image

你看到的 v-bind attribute 被称为 指令 。指令带有前缀 v- ,以表示它们是 Vue 提供的特殊 attribute,代码的意思就是将这个元素节点的 title attribute 和 Vue 实例的 content property 保持一致”

如果你在控制台进行修改 vm.content 的值,绑定的数据依旧会发生变化

注:使用 v-bind 需要头部引入一个约束

<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">

如果使用 IDEA 安装 Vue.js 插件 会有提示补全

(二) 条件判断

条件判断使用的指令就是 v-ifv-else-ifv-else

来看两个例子,首先是对于 true 或者 false 的判断

<div id="hello-3">
  <h2 v-if="isBoy">是男孩</h2>
  <h2 v-else>是女孩</h2>

</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
  var vm = new Vue({
      el: "#hello-3",
      data:{
        isBoy: true
      }
  })
</script>

默认显示是男孩,我们接着在控制台修改为false

ecb43fb826964f4d846635ac32f89f30~tplv-k3u1fbpfcp-zoom-1.image

接着是对于值的判断,我们拿一个比较成绩的小例子,不过对数值的约束还是不够严谨的,仅仅为了讲解 if 这个例子,明白意思就行

<div id="hello-3">
  <h2 v-if="score < '60'">成绩不及格</h2>
  <h2 v-else-if="score >= '60' && score < '80'">成绩及格</h2>
  <h2 v-else>成绩优秀</h2>

</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
  var vm = new Vue({
      el: "#hello-3",
      data:{
          score: 66
      }
  })
</script>

在结果中继续修改看看

30ad3e2eaea54082bb0f6c3b013ca947~tplv-k3u1fbpfcp-zoom-1.image

(三) 循环

通过 v-for 就可以进行循环遍历,真例如 java 中的 增强for 只不过是把 冒号 换成了 in,students 对应 data 中的数组名,student 代表其中的每一项,通过 XXX.xx 的形式取出具体的属性值

<div id="hello-4">
  <li v-for="student in students">
    {{student.name}}
  </li>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
    var vm = new Vue({
        el: "#hello-4",
        data: {
            students: [{name: '张三'}, {name: '李四'}, {name: '王五'}]
        }
    })
</script>

试着在控制台 push 一个新的,同样会更新出来

34bfb7fab6364540a84ed70789324469~tplv-k3u1fbpfcp-zoom-1.image

说明:这里演示的只是最基本的一种情况,很多时候,若遍历的数组中为对象,且对象有多个值,例如含有 id 这样的值,一般会将这种唯一的 id 值作为 key 值,例如:

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute:

建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。

(四) 事件绑定

经常我们需要通过点击一些按钮或者标签组件等,使得用户可以与应用进行交互,也就是进行事件绑定,在 Vue 中我们可以通过 v-on 指令添加一个事件监听器来进行

注:使用 v-on 引入约束

<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">

示例代码

<div id="hello-5">
  <button v-on:click="helloWorld">你好世界</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
    var vm = new Vue({
        el: "#hello-5",
        data: {
            content: "Hello World !"
        },
        methods: {
            helloWorld: function () {
                alert(this.content);
            }
        }
    })
</script>

可以看到,通过 v-on:click 就将 helloWorld 这个事件绑定了,而事件的具体逻辑需要定义在 Vue 对象的 methods 中

(五) 双向绑定

早在开篇介绍 MVVM 架构模式的时候,图中就提到了 View 和 ViewModel 之间的双向绑定,通俗的说就是 :当数据发生变化时,视图也变化,而当视图发生变化的时候,数据也跟着变化

其实在前面的基本语法中,我们已经能很明显的体会到了前半句,即修改 data 中的数据,从而引起视图中的变化,我们这里就重点提一下后半句

首先,Vue 提供了 v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定

从常见的表单中的几种形式来讲,我们可以使用 v-model 指令在表单的 inputtextarea>select 等上进行数据的双向绑定,它可以根据控件类型选取正确的方法来更新元素

不过使用 v-model 指令后会忽略表单原先的 value、checked、selected 等的初始值,而总将 Vue 实例中的数据最为数据源

input 中 ,输入文本

<div id="hello-6">
  输入: <input type="text" v-model="content" > 输出: {{content}}
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
    var vm = new Vue({
        el: "#hello-6",
        data: {
            content: "Hello World !"
        },
    })
</script>

在输出的位置使用两组大括号进行 content 这个值的回显我们之前就已经能做到了,而我们在 input 的属性中使用 v-model 进行对于 content 的绑定,这样就可以使得输入框中输入的值可以直接影响 data 中 content 的值,即随着你 input 中输入值的修改,随之输出位置的内容也会变化

790b7179c9bf47289f3030b704a84856~tplv-k3u1fbpfcp-zoom-1.image

input 中 ,单选框

<div id="hello-6">
  性别:
  <input type="radio" name="gender" value="男" v-model="gender">男
  <input type="radio" name="gender" value="女" v-model="gender">女
  输出: {{gender}}
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
    var vm = new Vue({
        el: "#hello-6",
        data: {
            gender: '男'
        },
    })
</script>

效果显示

5e12c55bf13244deb0b7c8ff30a8cefd~tplv-k3u1fbpfcp-zoom-1.image

select 中

<div id="hello-6">
  <select v-model="choose">
    <option value="" disabled>---请选择---</option>
    <option>A-苹果</option>
    <option>B-樱桃</option>
    <option>C-西瓜</option>
  </select>
  输出: {{choose}}
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script>
    var vm = new Vue({
        el: "#hello-6",
        data: {
            choose: ''
        },
    })
</script>

91fa386db59344679102376e7282ac08~tplv-k3u1fbpfcp-zoom-1.image

(六) Vue组件

Vue 中组件也是一个很重要的概念,例如一个页面中,头部、底部、侧边栏、主内容区 都可以看做一个一个组件,不过有一些组件是固定的,例如头部,还有一些是变换的例如内容区

Vue 中就允许我们使用小型、独立和通常可复用的组件构建大型应用

051676f630fe46578bd95eda69b425ef~tplv-k3u1fbpfcp-zoom-1.image

注:实际都是创建 .vue 模板文件,并不会用直接在页面中书写的这种形式,仅为讲解方便

直接拿一个简单,不过还算相对完善的案例来进行讲解‘

先说一下最终我们想干嘛,例如 div 或者 input 等等 都是一个一个标签,我们现在向做的就是通过创建自定义组件模板,自定义出一个这样的标签,我们在需要的地方只需要引用这个标签,我们就可以达到显示出模板中想要的效果,达到抽取复用的效果

首先使用 Vue.component....... 这样的格式创建组件,在其中 ideal-20 就是组件标签的名字, template 就代表模板中的内容,props 代表我们在引用处传入的参数名

接着在一个已经绑定好的 hello-7 的 div 中引入自定义组件标签 ideal-20,而我们想要遍历 data 中的 fruits 数组,在 ideal-20 属性中进行 for 遍历即可,同时我们需要将每一项通过 v-bind:ideal="item" 绑定参数到组件模板中,因为数组不是一个普通的数组,所以赋 id 为 key值

<div id="hello-7">
  <ideal-20 v-for="item in fruits" v-bind:ideal="item" v-bind:key="item.id"></ideal-20>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

<script>
    // 定义名为 todo-item 的新组件
    Vue.component('ideal-20', {
        props: ['ideal'],
        template: '<li>{{ideal.name}}</li>'
    })
    var vm = new Vue({
        el: "#hello-7",
        data: {
            fruits: [
                {id: 0, name: '苹果'},
                {id: 1, name: '樱桃'},
                {id: 2, name: '山竹'}
            ]
        }
    })
</script>

效果展示

868450b56ae2498bbf7dea817b3c0b98~tplv-k3u1fbpfcp-zoom-1.image

(七) Axios 入门

首先我们需要提一下,为什么要用这个东西呢?

我们在以前传统的开发中,我们一般会使用 Ajax 进行通信,而 Vue,js 作为一个视图层框架,并不支持 Ajax 的通信功能,所以可以使用 Axios 来实现 Ajax 的异步通信

首先看一下它的特点:

  • 从浏览器中创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防御 XSRF

首先我们拿一段 json 来模拟数据

{
  "name": "BWH_Steven",
  "blog": "www.ideal-20.cn",
  "about": {
    "country": "中国",
    "phone": "13888888888"
  },
  "students": [
    {
      "id": 0,
      "name": "张三"
    },
    {
      "id": 1,
      "name": "李四"
    },
    {
      "id": 2,
      "name": "王五"
    }
  ]
}

通过下图我们就可以知道 我们可以将代码写到 mounted() 中去

131256b4363a4a37899a60a056072c59~tplv-k3u1fbpfcp-zoom-1.image

接着就是使用的代码了

首先除了引入 Vue 还需要引入 Axios 的 CDN,在 mounted() 方法中,去拿到这个json文件,同时将 response.data 也就是拿到的值,赋值给我们在 data() 中定义的 info 中

注意:data 和 data() 是不一样的

接着在绑定好的 hello-8 div 中就可以调用回显了

说明:为什么给 v-clock 添加了一个样式呢,这是因为,显示数据的过程是先显示出 {{info.name}} 这样的字样,拿到值后,再去渲染,如果网速慢的情况下可以看到 info.name 的,体验不是很好

<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    [v-clock] {
      display: none;
    }
  </style>
</head>
<body>
<div id="hello-8" v-clock>
  <div>{{info.name}}</div>
  <div>{{info.blog}}</div>
  <div>{{info.about.country}}</div>
  <div>{{info.about.phone}}</div>
  <div>{{info.students[0].name}}</div>
</div>

<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>

    var vm = new Vue({
        el: "#hello-8",
        data() {
            return {
                info: {}
            }
        },
        mounted() {
            axios.get("../json/data.json").then(response => (this.info = response.data));
        }
    })
</script>

</body>
</html>

(八) 计算属性

这一段,我认为官方文档说的还是比较清楚的

模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。例如:

<div id="example">
  {{ message.split('').reverse().join('') }}
</div>

在这个地方,模板不再是简单的声明式逻辑。你必须看一段时间才能意识到,这里是想要显示变量 message 的翻转字符串。当你想要在模板中多包含此处的翻转字符串时,就会更加难以处理。

所以,对于任何复杂逻辑,你都应当使用 计算属性

<div id="hello-9">
  <p>原始数据: "{{ message }}"</p>
  <p>翻转数据: "{{ reversedMessage }}"</p>
</div>


<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

<script>
    var vm = new Vue({
        el: '#hello-9',
        data: {
            message: 'Hello'
        },
        computed: {
            // 计算属性的 getter
            reversedMessage: function () {
                // `this` 指向 vm 实例
                return this.message.split('').reverse().join('')
            }
        }
    })
</script>

结果:

原始数据: "Hello"

翻转数据: "olleH"

这里我们声明了一个计算属性 reversedMessage 。我们提供的函数将用作 property vm.reversedMessage 的 getter 函数:

console.log(vm.reversedMessage) // => 'olleH'
vm.message = 'Goodbye'
console.log(vm.reversedMessage) // => 'eybdooG'

你可以打开浏览器的控制台,自行修改例子中的 vm。 vm.reversedMessage 的值始终取决于 vm.message 的值。

你可以像绑定普通 property 一样在模板中绑定计算属性。Vue 知道 vm.reversedMessage 依赖于 vm.message ,因此当 vm.message 发生改变时,所有依赖 vm.reversedMessage 的绑定也会更新。而且最妙的是我们已经以声明的方式创建了这种依赖关系:计算属性的 getter 函数是没有副作用 (side effect) 的,这使它更易于测试和理解。

计算属性和方法的区别 ?

看到这里,你会不会觉得,貌似我用方法也可以实现这种效果啊,将具体的业务逻辑放在定义的方法中,但是他们最大的区别是 计算属性是基于它们的响应式依赖进行缓存的 ,也就是说,我们上文中所依赖的 message 不发生改变,reversedMessage 会马上获取之前的结果,就不用再次执行函数了,计算属性可以帮我们节省大量的性能开销,不过如果我们并不希望出现缓存内容,就可以使用方法来代替它

(九) 插槽 Slot

在 2.6.0 中,我们为具名插槽和作用域插槽引入了一个新的统一的语法 (即 v-slot 指令)。它取代了 slot 和 slot-scope 这两个目前已被废弃但未被移除且仍在文档中的 attribute。新语法的由来可查阅这份 RFC。

这块写的太浅了,不看也罢

插槽就是子组件给父组件一个占位符即 <slot></slot> 父组件就能在这个占位符,填一些模板或者 HTML 代码

简单点理解就是组件套组件

就像下面我定义了三个组件,ideal是父组件,在其中用 slot 进行占位,同时用 name 属性指向到了这两个子组件 ideal-title 和 ideal-content,而为了子组件中显示的数据来自服务器(模拟)所以需要动态地显示,即通过传参(前面讲解组件模板有说过),配合遍历等读出 data 中的数据即可

<div id="hello-10">
  <ideal>
    <ideal-title slot="ideal-title" v-bind:title="title"></ideal-title>
    <ideal-content slot="ideal-content" v-for="contentItem in contents" v-bind:content="contentItem"></ideal-content>
  </ideal>
</div>


<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>

<script>
    Vue.component("ideal", {
        template: '<div>\
                    <slot name="ideal-title"></slot>\
                      <ul>\
                        <slot name="ideal-content"></slot>\
                      </ul>\
                   </div>'
    })
    
    Vue.component("ideal-title", {
        props: ['title'],
        template: '<div>{{title}}</div>'
    })
    
    Vue.component("ideal-content", {
        props: ['content'],
        template: '<li>{{content}}</li>'
    })

    var vm = new Vue({
        el: '#hello-10',
        data: {
            title: "理想二旬不止",
            contents: ["Java", "Linux", "数据库"]
        }
    })
</script>

结果如下:

e4b43b60e26f4d10982afc39cc462487~tplv-k3u1fbpfcp-zoom-1.image

四 Vue 入门

(一) 创建 Vue-cli 项目

Vue-cli 是官方提供的一个用于快速创建 Vue 项目的脚手架,可以简单的理解为 Maven ,即创建时选择一个骨架那种感觉,能让开发更加便捷

(1) 准备

A:安装 Node.js

  • Node.js 去官网或者中文网进行下载

cmd 下输入 node -v ,出现版本号即正常,输入 npm -v 同样出现版本号即正常

  • 将 Node.js 的镜像调整为淘宝镜像加速(cnpm)
# -g 代表全局安全 推荐此方法
npm install cnpm -g

# 还有一种办法就是每次使用 npm 都在后面加一串字符串,不推荐
npm install --registry=https://registry.npm.tabao.org

安装后打开此路径(abc是我这台机器的用户名,根据自己的来):

C:\Users\abc\AppData\Roaming\npm\node_modules

正常情况下里面会有安装好的 cnpm,接着我们就开始安装 vue-cli

B:安装 vue-cli

cnpm install vue-cli -g

安装后在 npm 文件夹下打开 cmd 输入 vue-list ,若出现下图这种星状内容,则完毕

4b4bf7f785104c49aca05f12d14a3243~tplv-k3u1fbpfcp-zoom-1.image

C:创建 vue-cli 程序

自己在想要的位置创建一个目录,选择基于 webpack 的 vue 应用程序

此文件夹下的 cmd 中输入命令

vue init webpack vue_02_myvue

输入一些基本信息,例如 项目名 作者名

下面的内容如果有选项的回车配合 n(也就是no)进行

636d05fb2b094b81a9bff618ada56b90~tplv-k3u1fbpfcp-zoom-1.image

这时,它会询问你是否自动执行 npm install(如下),是的话则会自动安装一些依赖,点击否,需要自行再输入命令安装,所以选择是就行了

Should we run npm install for you after the project has been created? (recommended) npm

完成之后,项目中的 node_modules 就会多出很多很多依赖

再接着,它又会提醒初始化好了,你如果想启动就可以执行这两条,第一句是从外面的文件夹进入到我自定义的那个项目文件夹中,第二句则是启动

734e917f114841f087a4e1e1698e6e24~tplv-k3u1fbpfcp-zoom-1.image

出现如果所示内容则启动成功,通过后面的地址和端口就可以访问

fe3e00a889e74b10a19f3fc25a0a9e40~tplv-k3u1fbpfcp-zoom-1.image

找个编辑器看一下,我用 IDEA Open进这个文件夹来,就可以进行修改了,具体的代码文件还是在 src 目录下,同时还可以配置 IDEA 的 Terminal 为有管理员权限的 cmd 或者终端,能更便捷一些

如何快速创建项目

  • 可以通过 HBuilder 进行相对快速的创建项目,其新建中直接就可以创建 vue 项目 以及终端运行
  • 在想创建项目的目录下终端输入 vue ui 进入图形界面(此方法需要 vue-cli 版本为 3.x ,通过 vue --version 查询到 vue-cli 的版本 例如为 2.9.6 是不能使用的,可用的命令可以通过 vue -h 查看 )

(二) 简单认识 Webpack

(1) 认识安装

盖菜我们创建 vue 项目的时候,选择的是 webpack 进行打包,但是都是自动化的过程,我们手动的操作一下,能更好的理解

webpack是一个现代 Javascript应用程序的静态模块打包器( module bundler)。当webpack处理应用程序时,它会递归地构建一个依赖关系 Dependency graph),其中包含应用程序需要的毎个模块,然后将所有这些模块打包成一个或多个 bundle

webρack是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散耦合的模块按照

依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分离,等到实际

需要时再异步加载。通过 loader转换,任何形式的资源都可以当做模块,比如 Commonis、AMD、ES6、CSS、JSON、 Coffee Script、LESS等;

安装 webpack、webpack-cli ,如果 npm 不太慢先考虑使用 npm 再考虑使用 cnpm

cnpm install webpack -g

cnpm install webpack-cli -g

通过 webpack -vwebpack-cli -v 查看是否出现版本号确定安装是否成功

(2) 使用 webpack

  • 创建项目(IDEA 的话,直接创建一个普通文件夹 Open进入就行了)
  • 新建一个 modules 目录,放置 JS 模块等内容
  • 在 modules 下创建模块文件,例如 demo.js 用于编写 Js 模块相关代码,例如
exports.test = function () {
    document.write("<h2>理想二旬不止</h2>")
}
  • 在 moduels 下创建 main.js ,这是一个入口文件,用于打包时设置 entry 属性对应
var demo = require("./demo")
demo.test();
  • 在项目根目录下创建 webpack.config.js 文件,用于配置
module.exports = {
    entry: "./modules/main.js",
    output: {
        filename: "./js/bundle.js"
    }
};
  • 在 terminal 中输入 webpack 命令进行打包(进入项目目录后 输入 webpack 就行了,这是运行结果)
abc@LAPTOP-5T03DV1G MINGW64 /f/develop/IdeaProjects/framework-code/vue/webpack_01_first
$ webpack
Hash: 7f61ef9440a6bab63058
Version: webpack 4.44.1
Time: 334ms
Built at: 2020-09-05 4:18:40 PM
         Asset        Size  Chunks             Chunk Names
./js/bundle.js  1020 bytes       0  [emitted]  main
Entrypoint main = ./js/bundle.js
[0] ./modules/main.js 42 bytes {0} [built]
[1] ./modules/demo.js 82 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each e
nvironment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
  • 打包后项目目录多出 dist 文件夹 其中有一个 js 文件夹,放着打包的 js,创建index.html 引入此 js
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
  <script src="dist/js/bundle.js"></script>
</body>
</html>
  • 页面效果如下:

f07d5237a749402382504d70958078f6~tplv-k3u1fbpfcp-zoom-1.image

补充:配置文件中可能会有哪些内容

  • entry:入口文件,指定 Web Pack用哪个文件作为项目的入口
  • output:输出,指定 Web pack把处理完成的文件放置到指定路径
  • module:模块,用于处理各种类型的文件plugins:插件,如:热更新、代码重用等
  • resolve:设置路径指向
  • watch:监听,用于设置文件改动后直接打包

(三) 简单认识 Vue Router 路由

Vue Router是 Vue.js 的官方路由器。它与 Vue.js 核心深度集成,使使用 Vue.js 轻松构建单页应用程序变得轻而易举。功能包括:

简单的说,可以实现一些页面的跳转,例如我们头部的内容是不变的,内容部分需要根据链接改变

  • 嵌套路线/视图映射
  • 模块化,基于组件的路由器配置
  • 路由参数,查询,通配符
  • 查看由Vue.js过渡系统提供动力的过渡效果
  • 细粒度的导航控制
  • 与自动活动CSS类的链接
  • HTML5历史记录模式或哈希模式,在IE9中具有自动回退
  • 可自定义的滚动行为

安装步骤:

由于 vue-router 是一个插件包,还是老办法,npm/cnpm

npm install vue-router --save-dev

安装后如果有一些问题,根据提示,输入对应命令即可,就像我遇到了提示输入 npm audit fix

创建好项目后,删掉默认的 HelloWorld那个组件,然后再 components 中新建两个自定义组件,例如我创建的 FirstDemo.vue 和 Main.vue 前者是一个子页面,后者代表主页面,随便自拟

FirstDemo.vue

<template>
  <h1>第一个Demo页面</h1>
</template>

<script>
  export default {
    name: "FirstDemo.vue"
  }
</script>

<style scoped>

</style>

Main.vue

<template>
  <h1>首页</h1>
</template>

<script>
  export default {
    name: "Main.vue"
  }
</script>

<style scoped>
</style>

接着创建 router 文件夹,以及其中的 index.js 主配置

注:如果在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能

import Vue from 'vue'
import VueRouter from 'vue-router'
import FirstDemo from '../components/FirstDemo'
import Main from '../components/Main'

Vue.use(VueRouter);

export default new VueRouter({
  routes: [
    {
      // 路由路径
      path: "/firstDemo",
      name: 'firstDemo',
      // 跳转的组件
      component: FirstDemo
    },
    {
      // 路由路径
      path: "/main",
      name: 'main',
      // 跳转的组件
      component: Main
    }
  ]
})

修改 main.js 这个入口文件

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

Vue.use(router);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  //配置路由
  router,
  components: {App},
  template: '<App/>'
})

以及正式的书写页面,引入链接

<template>
  <div id="app">
    <h1>理想二旬不止</h1>
    <router-link to="/main">首页</router-link>
    <router-link to="/firstDemo">第一个Demo页面</router-link>
    <router-view></router-view>
  </div>
</template>

<script>

  export default {
    name: 'App',
  }
</script>

<style>
  #app {
    font-family: 'Avenir', Helvetica, Arial, sans-serif;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    color: #2c3e50;
    margin-top: 60px;
  }
</style>

(四) Vue + ElementUi 基本使用

创建名字为 vue_03_vue_elementui 的项目,同时安装 vue-router、e1ement-ui、sass-loader 、node-sass 插件

# 创建项目
vue init webpack vue_03_vue_elementui

# 进入工程目录
cd vue_03_vue_elementui
# 安装vue-router
npm install vue-router --save-dev
# 安装e1ement-ui
npm i element-ui -S
# 安装依赖
npm install
# 安装SASS加载器
cnpm install sass-loader node-sass --save-dev
# 启动测试
npm run dev

补充:Npm命令解释

  • npm install moduleName :安装模块到项目目录下
  • npm install - g moduleNMame :-g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix的位置
  • npm install - save moduleName :--save 的意思是将模块安装到项目目录下,并在package文件的 dependencies 节点写入依赖,-S为该命令的缩写
  • npm install -save -dev moduleName :--save-dev 的意思是将模块安装到项目目录下,并在 package 文件的 devdependencies节点写入依赖, -D为该命令的缩写

接着就可以在编辑器中打开了,看个人选择,我这里用 IDEA 打开,打开后注意看一下 modules 文件夹中是否已经把 router sass 等内容成功安装了

接着将默认的 HelloWorld 那个组件和默认 logo 删掉,开始编写代码,创建一个 views 文件夹用来放视图

创建 Login.vue 和 Main.vue

Login.vue

<template>
  <h1>主页面</h1>
</template>

<script>
  export default {
    name: "Main.vue"
  }
</script>

<style scoped>
</style>

Main.vue

<template>
  <div>
    <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
      <h3 class="login-title">欢迎 登录</h3>
      <el-form-item label=" 账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      </el-form-item>
      <el-form-item label=" 密码" prop="password">
        <el-input type="password" placeholder=" 请输入密码" v-model="form.password"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit( 'loginForm' )">登录</el-button>
      </el-form-item>
    </el-form>
    <el-dialog
      title="温馨提示"
      :visible.sync="dialogVisible"
      width="30%"
      :before-close="handLeClose">
      <span>请输入账号和密码</span>
      <span slot="footer" class="dialog- footer">
        <el-button type="primary" @click="dialogVisible = false">确定</el-button>
      </span>
    </el-dialog>
  </div>

</template>


<script>
  export default {
    name: "Login",
    data() {
      return {
        form: {
          username: '',
          password: ''
        },
        //表单验证,需要在el-form-item 元素中增加prop 属性
        rules: {
          username: [
            {required: true, message: " 账号不可为空", trigger: 'blur'}
          ],
          password: [
            {required: true, message: " 密码不可为空 ", trigger: 'blur'}
          ]
        },
        //对话框显示和隐藏
        dialogVisible: false
      }
    },
    methods: {
      onSubmit(formName) {
        //为表单绑定验证功能
        this.$refs[formName].validate((valid) => {
          if (valid) {
            //使用vue-router路由到指定页面,该方式称之为编程式导航
            this.$router.push("/main");
          } else {
            this.dialogVisible = true;
            return false;
          }
        });
      }
    }
  }
</script>


<style lang="scss" scoped>
  .login-box {
    border: 1px solid #DCDFE6;
    width: 350px;
    margin: 40px auto;
    padding: 35px 35px 15px 35px;
    border-radius: 5px;
    -webkit-border-radius: 5px;
    -moz-border-radius: 5px;
    box-shadow: 0 0 25px #909399;
  }

  .login-title {
    text-align: center;
    margin: 0 auto 40px auto;
    color: #303133;
  }
</style>

创建 router 文件夹,以及其中的 index.js,配置好跳转内容

index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '../views/Login'
import Main from '../views/Main'

Vue.use(VueRouter);

export default new VueRouter({
  routes: [
    {
      path: "/main",
      component: Main
    },
    {
      path: "/login",
      component: Login
    }
  ]
})

修改 main.js ,使用 router 和 elementui,关于 router 前面就说过,至于后者,照着官网起步文档就明白了

https://element.eleme.cn/#/zh-CN/component/quickstart

main.js

import Vue from 'vue'
import App from './App'

import router from './router'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false;

Vue.use(router);
Vue.use(ElementUI);

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  render: h => h(App)
});

App.vue

<template>
  <div id="app">
    <h1>理想二旬不止</h1>
    <router-link to="/main">首页</router-link>
    <router-link to="/login">登录页面</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

到这里就写好了,我们可以开始运行了,但是运行时,我分别出现了如下错误

TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined

Module build failed: TypeError: this.getResolve is not a function

经查阅后,修改项目目录下 package.json 中的 sass-loder 的版本 从 10.0.2 到 8.0.2 到 7.3.1 才可以正常通过 npm run dev 运行

"sass-loader": "^7.3.1",

注:修改配置后需要重新 npm install 或者 cnpm install

展示一下最终效果:

点击首页效果:

f1114d22e84945aa9a615c8a69607123~tplv-k3u1fbpfcp-zoom-1.image

点击登录页面效果:

277c69c16c40493b8a56ba4d9fff48d2~tplv-k3u1fbpfcp-zoom-1.image

五 Vue和Java数据交互简单案例

最后,在某马上找了一个现成的页面案例,简单搭了下后台跑了一下,也算巩固一下最前面的基础语法,后台就基本的 SSM ,给了三个接口方法,作为一个后端,这应该算基本功了哇

/user/findAll/user/indById/user/updateUser

就是简单的查询和一个更新操作,查询的主体是一个用户类,有这么几个基本字段

public class User implements Serializable {    
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private String sex;
    private String email;
    ......
}

页面中承接的数据的关键代码如下

首先是关于所有用户数据展示的,通过一个对于 userList 的遍历,然后通过大括号组和 X.x 的形式取出属性值

<tr v-for="u in userList">
  <td><input name="ids" type="checkbox"></td>
  <td>{{u.id}}</td>
  <td>{{u.username}}
  </td>
  <td>{{u.password}}</td>
  <td>{{u.sex}}</td>
  <td>{{u.age}}</td>
  <td class="text-center">{{u.email}}</td>
  <td class="text-center">
    <button type="button" class="btn bg-olive btn-xs">详情</button>
    <button type="button" class="btn bg-olive btn-xs" @click="findById(u.id)">编辑</button>
  </td>
</tr>

点击编辑后执行对于当前用户的查询方法,用于回显,下面通过 v-model 进行与 user 的绑定(js后面给出)

<div class="box-body">
  <div class="form-horizontal">


    <div class="form-group">
      <label class="col-sm-2 control-label">用户名:</label>
      <div class="col-sm-5">
        <input type="text" class="form-control" v-model="user.username">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">密码:</label>
      <div class="col-sm-5">
        <input type="text" class="form-control" v-model="user.password">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">性别:</label>
      <div class="col-sm-5">
        <input type="text" class="form-control" v-model="user.sex">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">年龄:</label>
      <div class="col-sm-5">
        <input type="text" class="form-control" v-model="user.age">
      </div>
    </div>
    <div class="form-group">
      <label class="col-sm-2 control-label">邮箱:</label>
      <div class="col-sm-5">
        <input type="text" class="form-control" v-model="user.email">
      </div>
    </div>
  </div>
</div>

要实现数据交互,最重要的还是定义数据,与使用 axios 进行异步请求

var vue = new Vue({
    el: "#app",
    data: {
        user: {id: "", username: "", password: "", age: "", sex: "", email: ""},
        userList: []
    },
    methods: {
        findAll: function () {
            var _this = this;
            axios.get("user/findAll.do").then(function (response) {
                _this.userList = response.data;
                console.log(_this.userList);
            }).catch(function (err) {
                console.log(err);
            });
        },
        findById: function (userid) {
            var _this = this;
            axios.get("user/findById.do", {
                params: {
                    id: userid
                }
            }).then(function (response) {
                _this.user = response.data;
                $('#myModal').modal("show");
            }).catch(function (err) {
            });

        },
        update: function (user) {
            var _this = this;
            axios.post("user/updateUser.do", _this.user).then(function (response) {
                _this.findAll();
            }).catch(function (err) {
            });
        }
    },
    created() {
        this.findAll();
    }
});

上述代码其实很好理解,首先定义了 user 和 userList 两个数据,userList 就是前面展示所有用户数据的一个遍历内容,用来承载 findAll 后的数据,user 则是对于进行单个用户查询,即修改时回显当前用户旧信息的一个承载实体,因为查询所有的操作是一开始就进行,所以在 created() 中就执行 findAll 方法,在 methos 中创建查和改的方法,通过 axios 进行 get 或者 post 请求,同时将返回的结果进行处理

说明: .then 中的是请求成功后执行的内容, .catch 中是请求失败后执行的内容

注意:最关键的一个内容就是在 axios 前定义了 var _this = this 如果有接触过小程序可能会感到很熟悉,这里定义的原因是因为 例如在 axios 中有这样的语句 _this.userList = response.data; 如果 userList 中前直接使用 this,这就代表着查找 axios 中的此内容,但我们明显想指代的是 data 中的 userList,所以此定义 _this 步骤不可省略

效果如下:

查询所有

e6061bb01566465289975b84a435e36b~tplv-k3u1fbpfcp-zoom-1.image

查询当前用户以及修改

48956c7e07e84543aa2af5585fff0d72~tplv-k3u1fbpfcp-zoom-1.image

六 结尾

如果文章中有什么不足,欢迎大家留言交流,感谢朋友们的支持!

如果能帮到你的话,那就来关注我吧!如果您更喜欢微信文章的阅读方式,可以关注我的公众号

一个坚持推送原创开发技术文章的公众号:理想二旬不止

4399bb5f8a2f48908e1c618121c651b6~tplv-k3u1fbpfcp-zoom-1.image


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK