vue 的基础应用(上)

Java工程师老刘 2021-04-07 18:36:57
vuex Jquery Vue.js


Tip: vue 的基础应用分上下两篇,上篇是基础,下篇是应用

初步认识 vue一文中,我们已经写了一个 vue 的 hello-world。对 vue 已经有了一个大概的印象。

接下来我们应该掌握 vue 的最基础知识,学会 vue 的基本应用。

比较好的方法就是花个几天的时间将 vue 官网的基础篇尽量走一遍,写一写例子。以下是 vue 2.x 的基础篇的目录:

- 教程 2.x
 - 基础
 - 安装
 - 介绍
 - Vue 实例
 - 模板语法
 - 计算属性和侦听器
 - Class 与 Style 绑定
 - 条件渲染
 - 列表渲染
 - 事件处理
 - 表单输入绑定
 - 组件基础

:如果你像笔者一样,只有 jQuery 开发的经验,在看基础篇的过程种,肯定会有很多的不懂之处,先看下去,把能看懂的先看完。

本文记录的是笔者当初看 vue 基础篇遇到的一些重要的、不好理解的知识点,算是基础篇的一个补充或笔记。

Vue 实例

通过 new Vue() 来创建一个实例,其中 el 选项提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。

vue 实例会经历一系列的过程,比如数据侦测、模板编译、渲染到视图等,这就是 vue 实例的生命周期,vue 对外提供了生命周期的钩子函数,这就允许我们在 vue 的各个阶段插入一些我们的逻辑。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src='vue.js'></script>
</head>
<body>
<div id='app'>
<p>
{{message}}
</p>
</div>
<script>
// 通过 new Vue() 创建一个实例
var app = new Vue({
// 提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。
// 可以是 CSS 选择器,也可以是一个 HTMLElement 实例。
el: '#app',
// Vue 实例的数据对象
data:{
message: 'hello',
},
// 生命周期
created: function(){
console.log('实例被创建时触发')
},
mounted: function(){
console.log('被挂载时触发')
}
})
</script>
</body>
</html>

Tip: 后续不在提供完整的代码,省略 head、body 等。

模板语法

前文说过 vue 是声明式操作 dom 的框架。我们只需要描述状态与 dom 之间的映射关系即可,状态到视图的转换,框架会帮我们做,状态改变,视图也会自动更新。

而 vue 是通过模板来描述状态与 dom 之间的映射关系。所以模板的知识点稍微会多一点。

条件渲染

用 key 管理可复用的元素

Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

<div id='app'>
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
<button @click='toggleHandle'>切换</button>
</div>
<script>
var app = new Vue({
el: '#app',
data:{
loginType: 'username',
},
methods: {
toggleHandle: function(){
this.loginType = this.loginType === 'username' ? 'email' : 'username';
}
}
})
</script>

在上面的代码中切换 loginType 将不会清除用户已经输入的内容。因为两个模板使用了相同的元素,<input> 不会被替换掉——仅仅是替换了它的 placeholder。如果需要表达“这两个元素是完全独立的,不要复用它们”,只需添加一个具有唯一值的 key attribute 即可。

// 给 input 添加 key 属性
<input placeholder="Enter your username" key="username-input">
<input placeholder="Enter your email address" key="email-input">

v-if vs v-show

v-if 是真正的条件渲染;v-show 只是简单地切换元素的 CSS property display;

例如下面这种场景,点击一个新建按钮,显示弹框组件(custom-dialog),弹框中有一些 input 输入框,如果需要每次点击新建,弹框组件整个都重新生成,则可以使用 v-if;否则在弹框中输入了文字,通过 v-show 隐藏弹框,下次在显示时,可能之前输入的文字、错误信息都还存在。

<custom-dialog v-if='isShow'></custom-dialog>
<button @click='clickHandle'>新建</button>

表单输入绑定

v-model:在表单控件或者组件上创建双向绑定。

应用在表单控件上,请看示例:

<div id='app'>
<input v-model="message" placeholder="edit me"> <!-- {1} -->
<!--
<input type="text" :value='message' @input='handleInput' placeholder="edit me"> // {2}
-->
<p>Message is: {{ message }}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data:{
message: 'a'
},
methods: {
handleInput: function(e){
this.message = e.target.value
}
}
})
</script>

v-model 本质上不过是语法糖。行{1} 的本质其实是 行{2}。

v-model 在组件中的使用请看下文。

组件基础

上面介绍的其实是基础中最简单的部分。而组件是基础篇中最应该掌握的部分。

Vue.component()

可以通过 Vue.component() 注册或获取全局组件。请看示例:

 <div id='app'>
<p>{{message}}</p>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
<script>
// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
// 一个组件的 data 选项必须是一个函数
// 这样,每个组件的数据都是独立的
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
var app = new Vue({
el: '#app',
data: {
message: 'hello'
}
})
</script>

组件是可复用的 Vue 实例,且带有一个名字:在这个例子中是 <button-counter>

因为组件是可复用的 Vue 实例,所以它们与 new Vue() 接收相同的选项,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

通常一个应用会以一棵嵌套的组件树的形式来组织,这样就能完成一个功能很复杂的页面。

props

props 用于接收来自父组件的数据。请看示例:

 <div id='app'>
<!-- <button-counter v-bind:msg='message'></button-counter> -->
<!-- 缩写 -->
<button-counter :msg='message'></button-counter>
</div>
<script>
Vue.component('button-counter', {
props: ['msg'],
template: `<div> 来自父组件的信息: {{msg}} </div>`
})
var app = new Vue({
el: '#app',
data: {
message: 'hello'
}
})
</script>

v-bind:msg='message' 可以缩写成 :msg='message'

v-on

v-on 用在自定义元素组件上时,可以监听子组件触发的自定义事件。请看示例:

<div id='app'>
number: {{count}}
<!-- 父组件给子组件注册了事件 chang-count,事件的回调方法是 changCount -->
<button-counter v-on:chang-count='changCount'></button-counter>
</div>
<script>
Vue.component('button-counter', {
data: function(){
return {
num: 10
}
},
template: `<div> <!-- v-on:click 缩写 @click --> <button @click='triggerHandle'>触发</button> </div>`,
methods: {
triggerHandle: function(){
// 触发事件
this.$emit('chang-count', this.num++);
}
}
})
var app = new Vue({
el: '#app',
data: {
count: 0
},
methods: {
changCount: function(v){
this.count = v;
}
}
})
</script>

v-on 的语法糖是 @。

v-model

v-model 在表单控件或者组件上创建双向绑定。上文已经介绍了如何在表单上使用。而用在组件上,原理是相同的。请看示例:

 <div id='app'>
number: {{count}}
<!-- 父组件给子组件注册了事件 chang-count,事件的回调方法是 changCount -->
<custom-input v-model="count"></custom-input> <!-- {20} -->
<!-- <custom-input :value="count" @input='changCount'></custom-input> --> <!-- {21} -->
</div>
<script>
Vue.component('custom-input', {
props: ['value'],
data: function(){
return {
msg: this.value
}
},
template: `<div> <input :value='msg' @input='inputHandle'/> </div>`,
methods: {
inputHandle: function(e){
this.msg = e.target.value
// 触发事件
this.$emit('input', this.msg);
}
}
})
var app = new Vue({
el: '#app',
data: {
count: 10
},
methods: {
changCount: function(v){
this.count = v;
}
}
})
</script>

行{20} 与 行{21} 等效。

非父子组件通信

props 用于父组件给子组件传递数据;

子组件给父组件传递数据可以通过事件(例如 vm.$emit());

但非父子之间如何通信?

对于 d i s p a t c h dispatch 和 broadcast 最简单的升级方式就是:通过使用事件中心,允许组件自由交流,无论组件处于组件树的哪一层。由于 Vue 实例实现了一个事件分发接口,你可以通过实例化一个空的 Vue 实例来实现这个目的。—— vue 官网

简单来说,就是使用一个空的 Vue 实例作为中央事件总线,可以帮助我们解决兄弟组件之间的通信。请看示例:

<div id='app'>
<component-a></component-a>
<component-b></component-b>
</div>
<script>
Vue.component('componentA', {
data: function(){
return {
msg: '我是 componentA'
}
},
template: `<div> message: {{msg}} <button @click='send'>给兄弟发送数据</button> </div>`,
created: function(){
var that = this;
// 给事件中心注册事件
bus.$on('on-messageA', function(msg){
console.log('received: ' + msg)
that.msg = msg
})
},
methods: {
send: function(e){
// 给事件中心触发事件
bus.$emit('on-messageB', 'from componentA')
}
}
})
Vue.component('componentB', {
data: function(){
return {
msg: '我是 componentB'
}
},
template: `<div> message: {{msg}} <button @click='send'>给兄弟发送数据</button> </div>`,
created: function(){
var that = this;
bus.$on('on-messageB', function(msg){
that.msg = msg
})
},
methods: {
send: function(e){
console.log('from componentB')
bus.$emit('on-messageA', 'from componentB')
}
}
})
// 事件中心
var bus = new Vue()
var app = new Vue({
el: '#app'
})
</script>

这个例子中定义了两个组件,首先用 new Vue() 创建一个中央事件总线(bus),类似一个中介,接着组件(componentA、componentB)给 bus 注册事件,当点击按钮时触发 bus 的事件,并传递数据。

这种方式其实可以实现任何组件之间的通信,包括父子、兄弟、跨级等,因为在 bus 看来,我(bus)就是中介,其他组件只是我的客户。

Tip:项目比较大时,通常会使用 vuex,后续会介绍 vuex 这个状态管理工具。

父组件和子组件

vm. p a r e n t 可以取得父组件;通过 v m . parent 可以取得父组件;通过 vm. children 取得当前实例的直接子组件,并通过 vm.$refs 取得指定子组件。请看示例:

<div id='app'>
<component-a ref='comA'></component-a>
<component-a ref='comB'></component-a>
</div>
<script>
Vue.component('componentA', {
data: function(){
return {
msg: 'hello'
}
},
template: `<div> message: {{msg}} </div>`,
watch: {
msg: function(){
// 通过 vm.$parent 取得父组件
console.log(this.$parent.name)
// 通过 ref 指定子组件索引名称
// 通过 vm.$refs 取得子组件
console.log(this.$parent.$refs.comA.msg)
}
}
})
var app = new Vue({
el: '#app',
data: {
name: '我是父'
}
})
// 通过 vm.$children 直接更改子组件的数据
console.log(app.$children[1].msg = 'hello2')
</script>

通过插槽分发内容

插槽也可以叫 slot 内容分发。请看示例:

 <div id='app'>
<component-a ref='comA'>
<p>子元素的 slot 插槽将会被我替换</p> <!-- {30} -->
</component-a>
</div>
<script>
Vue.component('componentA', {
template: `<div> hello <slot></slot> </div>`,
})
var app = new Vue({
el: '#app',
})
</script>

我们在组件A中定义了一个插槽(<slot></slot>),父组件中的 p(行{30})将会替换子组件的 slot。

Tip: props、事件以及 slot 内容分发构成了 Vue 组件的 3 个 API 来源。

参考文章:https://www.jianshu.com/p/5bd2f7ad9da2

版权声明
本文为[Java工程师老刘]所创,转载请带上原文链接,感谢
https://my.oschina.net/u/3854427/blog/5011443

  1. 01_Nginx下载安装
  2. Spring Boot + Vue3 前后端分离 实战wiki知识库系统
  3. 01_ Download and install nginx
  4. Spring boot + vue3 front end and back end separation practical wiki knowledge base system
  5. vue实现tab选项卡
  6. 【vue】v-for倒序显示/JSON数据倒序
  7. 【vue】三种获取input值的写法
  8. 【vue】class、style的用法
  9. 「开源免费」基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之动态表单设计器(五)
  10. VSLAM前端:双目极线搜索匹配
  11. VSLAM前端:金字塔光流跟踪算法
  12. Vue realizes tab
  13. VSLAM前端:图像特征提取
  14. [Vue] V-for reverse display / JSON data reverse
  15. 独家对话阿里云函数计算负责人不瞋:你所不知道的 Serverless
  16. Three ways to get input value
  17. The usage of class and style
  18. "Open source and free" dynamic form designer of crudapi background management system of front end spa project based on Vue and Quasar (5)
  19. VSLAM front end: binocular epipolar search matching
  20. VSLAM front end: Pyramid optical flow tracking algorithm
  21. VSLAM front end: image feature extraction
  22. Exclusive dialogue with the person in charge of Alibaba cloud function computing: what you don't know about serverless
  23. 「开源免费」基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之序列号自定义组件(四)
  24. "Open source and free" serial number customization component of crudapi background management system of front end spa project based on Vue and Quasar (4)
  25. JavaScript 相似度排序
  26. Springboot项目搭建(前端到数据库,超详细)
  27. Less than 150 lines of code to write a python version of the snake
  28. 02_Nginx部署服务
  29. vue 快速入门 系列 —— vue 的基础应用(上)
  30. JavaScript similarity ranking
  31. 基于Vue和Quasar的前端SPA项目crudapi后台管理系统实战之布局菜单嵌套路由(三)
  32. Springboot project construction (front end to database, super detailed)
  33. 02_ Nginx Deployment Services
  34. vue 快速入门 系列 —— vue 的基础应用(上)
  35. Vue quick start series basic application of Vue
  36. Layout menu nested routing of front end spa project crudapi background management system based on Vue and Quasar (3)
  37. Vue quick start series basic application of Vue
  38. 一个好用的Visual Studio Code扩展 - Live Server,适用于前端小工具开发
  39. 基于Vue和Quasar的前端SPA项目实战之用户登录(二)
  40. css常用选择器总结
  41. Behind the miracle of the sixth championship is the football with AI blessing in the Bundesliga
  42. An easy to use Visual Studio code extension - live server, suitable for front-end gadget development
  43. 用 Python 抓取公号文章保存成 HTML
  44. User login of front end spa project based on Vue and Quasar (2)
  45. Summary of common selectors in CSS
  46. Using Python to grab articles with public number and save them as HTML
  47. To "restless" you
  48. 【免费开源】基于Vue和Quasar的crudapi前端SPA项目实战—环境搭建 (一)
  49. 【微信小程序】引入阿里巴巴图标库iconfont
  50. layui表格点击排序按钮后,表格绑定事件失效解决方法
  51. Unity解析和显示/播放GIF图片,支持http url,支持本地file://,支持暂停、继续播放
  52. 【vue】 export、export default、import的用法和区别
  53. [free and open source] crudapi front end spa project based on Vue and Quasar
  54. [wechat applet] introduces Alibaba icon library iconfont
  55. Layui table click Sort button, table binding event failure solution
  56. Element树形控件Tree踩坑:修改current-node-key无效
  57. Unity parses and displays / plays GIF images, supports HTTP URL, supports local file: / /, supports pause and resume playback
  58. Element树形控件Tree踩坑:修改current-node-key无效
  59. The usage and difference of export, export default and import
  60. Element tree control: invalid to modify current node key