Vue.js学习笔记

什么是Vue.js

Vue.js是一个轻巧、高性能、可组件化的MVVM库,同时拥有非常容易上手的API;
Vue.js是一个构建数据驱动的Web界面的库。
Vue.js是一套构建用户界面的 渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。Vue的核心库只关注视图层,并且非常容易学习,非常容易与其它库或已有项目整合。另一方面,Vue 完全有能力驱动采用单文件组件和 Vue生态系统支持的库开发的复杂单页应用。数据驱动+组件化的前端开发。
简而言之:Vue.js是一个构建数据驱动的 web 界面的渐进式框架。Vue.js 的目标是通过尽可能简单的 API实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统。

什么是 mvvm?

MVVM 是 Model-View-ViewModel 的缩写。mvvm 是一种设计思想。Model 层代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑;View 代表 UI 组件,它负责将数据模型转化成 UI 展现出来,ViewModel 是一个同步 View 和 Model 的对象。

简述Vue的响应式原理

当一个Vue实例创建时,vue会遍历data选项的属性,用 Object.defineProperty 将它们转为 getter/setter并且在内部追踪相关依赖,在属性被访问和修改时通知变化。
每个组件实例都有相应的 watcher 程序实例,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的 setter 被调用时,会通知 watcher 重新计算,从而致使它关联的组件得以更新。

Vue.js特点

简洁:页面由HTML模板+Json数据+Vue实例组成
数据驱动:自动计算属性和追踪依赖的模板表达式
组件化:用可复用、解耦的组件来构造页面
轻量:代码量小,不依赖其他库
快速:精确有效批量DOM更新
模板友好:可通过npm,bower等多种方式安装,很容易融入

开始学习

首先我是直接从写网页开始练习的,随便创建一个HTML文件,然后在中间直接用<script>引入

CDN

对于制作原型或学习,你可以这样使用最新版本:

<script src="https://unpkg.com/vue/dist/vue.js"></script>

或者用一个链接到一个明确的版本号和构建文件,以避免新版本造成的不可预期的破坏:

<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>

然后就能开始练习了,我是在这里学习的

遇到的问题

学习过程中发现
Elements in iteration expect to have ‘v-bind:key’ directives的报错
原因:VSCode中ESLint的功能,对vue进行了ESLint检查。
解决方法:File=>Preferences=>Settings,然后在搜索框搜索vetur.validation.template,将vetur.validation.templatetrue改为false

组件相关

data必须是一个函数

组件中我定义的data是如下的,但是,毫无作用。

data: {
  count: 0
}

改成这样才有用

data: function () {
  return {
    count: 0
  }
}

因为一个组件的 data 选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立的拷贝:否则就会出现其中一个组件修改了,其他组件也修改的事了。参考这里

重构模板

<div id="lordnb">
	<lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:name="post.name" v-bind:father="post.father" v-bind:content="post.content"></lord-nb>
</div>
<script>
Vue.component("lord-nb",{
	props : { 
		id : Number,
		name : String,
		father : {
			type: Object,
			// 对象或数组默认值必须从一个工厂函数获取
			default: function () {
				return { name: '黄帝' }
			}
		},
		content : {
			type: String,
			default :'<span style=\'color:yellow\'>黄色</span>'
		}
	},
	template :'<div class="blog-post"><h3>id:{{id}},name:{{name}},father:{{father.name}}</h3><div v-html="content"></div></div>'
})
var father2={
	name : "赵老大"
}
var lordnb = new Vue({
	el : '#lordnb',
	data: {
		posts: [
			{ id: 1, name: '赵', father : father2, content : '<span style=\'color:red\'>红色</span>'},
			{ id: 2, name: '钱' },
			{ id: 3, name: '孙' },
			{ id: 4, name: '李' }
		], content : '<span style=\'color:blue\'>蓝色</span>'
	}
})
</script>

如果想重构一下,觉得组件变得越来越复杂的时候改成这样

<div id="lordnb">
	//删减了其他,只保留了key,并增加了post
	<lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:post="post"></lord-nb>
</div>
Vue.component("lord-nb",{
	props : {
		//增加一个post
		post : Object,
		id : Number,
		name : String,
		father : {
			type: Object,
			// 对象或数组默认值必须从一个工厂函数获取
			default: function () {
				return { name: '黄帝' }
			}
		},
		content : {
			type: String,
			default :'<span style=\'color:yellow\'>黄色</span>'
		}
	},
	//template中所有属性增加前缀post.
	template :'<div class="blog-post"><h3>id:{{post.id}},name:{{post.name}},father:{{post.father.name}}</h3><div v-html="post.content"></div></div>'
})

然而此时,我发现了,浏览器会报错
Error in render: "TypeError: Cannot read property ‘name’ of undefined"

只有把father:{{ post.father.name }}改成father:{{father.name}}
并且把

<lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:post="post"></lord-nb>

增加为

<lord-nb v-for="post in posts" v-bind:key="post.id" v-bind:post="post" v-bind:father="post.father"></lord-nb>

时,错误提示才会去掉,且界面显示才正常。

具体原因不清楚,只因为我的这个father是对象?props一般好像支持值类型的比较多,对象一般用watch?我也不清楚,我初学者。

非 Prop 的特性

根据文中所说,大概意思就是说

Vue.component('good-title', {
	template : '<h3>标题</h3>',
	mounted: function () {
		console.log(this.$el.getAttribute('title-name'))
	}
});

如上所述,这里没props。然后在HTML中定义一个叫做title-name的属性,然后这个 title-name=“title” 特性就会自动添加到 的根元素上。

<good-title title-name="title"></good-title>

但是这样其实并不会在控制台显示title。
必须增加

<div id="sss">
	<good-title title-name="title"></good-title>
</div>

var sss = new Vue({
	el : '#sss'
})

此时,才会调用console.log(this.$el.getAttribute('title-name'))控制台才会显示title。为什么用mounted,而我用created页面会报错,具体参考Vue生命周期中mounted和created的区别

监听子组件事件

之前都是各种事件相关的都在模板里就定义好了,但如果想从组件里控制子元素中的事件,或者说一个组件集合控制子组件中的事件。参考这里

<blog-post :style="{ fontSize: postFontSize + 'em' }" id="enlarge" v-bind:title="title" v-bind:content="content"
		v-on:click="postFontSize += 0.1"></blog-post>
		
Vue.component('blog-post', {
	props: ['content','title'],
	template: `
		<div class="blog-post">
			<span>{{ title }}</span>
			<button>
				Enlarge text
			</button>
			<div v-html="content"></div>
		</div>
	`
})
var enlarge = new Vue({
	el:'#enlarge',
	data :{
		title : 'qwe',
		content : '<span>dasdadasd</span>',
		postFontSize: 1
	}
})

然而按钮怎么点都没用,这是因为我们定义的元素是div,事件也被定义到这个div中,而按钮是div的子元素,这个事件应该被定义到这个button中。那么该怎么做呢?
子元素可以通过调用内建的 $emit 方法 并传入事件名称来触发一个事件。

//这里定义了v-on:enlarge-text替代了v-on:click
<blog-post :style="{ fontSize: postFontSize + 'em' }" id="enlarge" v-bind:title="title" v-bind:content="content"
		v-on:enlarge-text="postFontSize += 0.1"></blog-post>

//下面button用v-on:click="$emit('enlarge-text')"将enlarge-text这个事件传到父组件blog-post中
Vue.component('blog-post', {
	props: ['content','title'],
	template: `
		<div class="blog-post">
			<span>{{ title }}</span>
			<button v-on:click="$emit('enlarge-text')">
				Enlarge text
			</button>
			<div v-html="content"></div>
		</div>
	`
})
var enlarge = new Vue({
	el:'#enlarge',
	data :{
		title : 'qwe',
		content : '<span>dasdadasd</span>',
		postFontSize: 1
	}
})

在组件上使用 v-model

v-model是一个指令,限制在<input>、<select>、<textarea>、components中使用,修饰符.lazy(取代 input 监听 change 事件)、.number(输入字符串转为有效的数字)、.trim(输入首尾空格过滤)。它其实是一个语法糖

<input v-model="searchText">

等价于

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

那么在组件上怎么使用v-model呢?
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的event。

<my-input id="myinput" v-model="searchText" v-bind:label = "mylabel"></my-input>

Vue.component("my-input",{
	props : ['label','value'],
	template : `
		<div>{{label}}
			<input v-bind:value="value" v-on:input="$emit('input', $event.target.value)">
			<p>{{ value }}</p>
		</div>
	`
})
new Vue({
	el: '#myinput',
	data : {
		mylabel : '姓名',
		searchText : ''
	}
})

通过插槽分发内容

根据这里,我怎么也弄不出它的效果,实际只需要增加样式就够了。

<style>
.demo-alert-box {
	padding: 10px 20px;
	background: #f3beb8;
	border: 1px solid #f09898;
}
</style>

methods与computed 的区别

computed:计算属性一般在数据量比较大,比较耗时的情况下使用(例如搜索),只有虚拟dom与真实dom不同的情况下会执行computed;

method:方法使用,如果使用了其中一个方法,其他的方法都会被执行,比较耗时,不管虚拟dom与真实dom一不一样都会执行。

<div id="lord">
	<p>{{ reversedMessageMethod() }}</p>
	<p>{{ reversedMessageComputed }}</p>
</div>
new Vue({
	el: '#lord',
		data: data,
	methods:{
		reversedMessageMethod: function () {
			return this.message1.split('').reverse().join('')
		}
	},
	computed : {
		reversedMessageComputed: function () {
			return this.message2.split('').reverse().join('')
		}
	}
})

注意:computed中的属性不能与data中的属性同名,否则会报错。

区别:computed计算的结果如果不发生改变就不会触发result这个函数。而methods中一般都是定义的需要事件触发的一些函数。每次只要触发事件,就会执行对应的方法。如果把computed中的方法写到method中会浪费性能。computed必须返回一个值页面绑定的才能取得值,而methods中可以只执行逻辑代码,可以有返回值,也可以没有。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值