大家好,又见面了,我是你们的朋友全栈君。
迫于无奈还得学下前端的东西,虽然本人学的是后端,但是很早也就听过了Vue很火,所以这里花一天时间学一些基础的Vue知识,至少保证能看懂吧!
1 Node和NPM
NPM是Node提供的模块管理工具,可以非常方便的下载安装很多前端框架,包括Jquery、AngularJS、VueJs都有,所以我们先安装node及NPM工具。
Node下载地址 Node下载地址
下载完后下一步下一步地安装即可,安装完成Node自带了NPM了
下载完后看看是否有npm,控制台查看下npm版本
C:\Users\12706>npm -v
6.4.1
npm默认的仓库地址是在国外网站,速度较慢,建议设置到淘宝镜像。但是切换镜像是比较麻烦的。推荐一款切换镜像的工具:nrm
我们首先安装nrm,这里-g
代表全局安装,然后查看下仓库列表,*表示当前使用的
C:\Users\12706>npm install nrm -g
npm WARN deprecated coffee-script@1.7.1: CoffeeScript on NPM has moved to "coffeescript" (no hyphen)
C:\Users\12706\AppData\Roaming\npm\nrm -> C:\Users\12706\AppData\Roaming\npm\node_modules\nrm\cli.js
+ nrm@1.1.0
added 324 packages from 564 contributors in 22.949s
C:\Users\12706>nrm ls
* npm ---- https://registry.npmjs.org/
cnpm --- http://r.cnpmjs.org/
taobao - https://registry.npm.taobao.org/
nj ----- https://registry.nodejitsu.com/
npmMirror https://skimdb.npmjs.com/registry/
edunpm - http://registry.enpmjs.org/
注意到npm当前使用的是国外的是国外的仓库地址,速度会比较慢,我们切换到淘宝镜像,顺便测试下速度
C:\Users\12706>nrm use taobao
verb config Skipping project config: C:\Users\12706/.npmrc. (matches userconfig)
Registry has been set to: https://registry.npm.taobao.org/
C:\Users\12706>nrm test npm
npm ---- 1211ms
注意:安装完后重启下电脑
2 Vue项目创建与安装
接下来就准备使用Vue了,首先创建工程,这里使用的开发工具是idea,由于第一次使用,所以全部进行了截图。
使用npm安装Vue
直接使用idea的中端来安装
Microsoft Windows [版本 10.0.10586]
(c) 2015 Microsoft Corporation。保留所有权利。
D:\my-vue>cd vue-demo
D:\my-vue\vue-demo>npm init -y #初始化 此时项目会多个package.json文件夹
Wrote to D:\my-vue\vue-demo\package.json:
{
"name": "vue-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
D:\my-vue\vue-demo>npm install vue --save #只针对该应用进行安装
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN vue-demo@1.0.0 No description
npm WARN vue-demo@1.0.0 No repository field.
+ vue@2.6.10
added 1 package from 1 contributor and audited 1 package in 2.624s
found 0 vulnerabilities
注意:
npm init -y #初始化 此时项目会多个package.json文件夹
npm install vue --save #只针对该应用进行安装 此时会多个node_modules文件夹,下面是Vue的源代码这些
最终就是下面这个样子
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello vue</title>
</head>
<body>
<div id="app">
<h1>
{
{name}} 很帅
</h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data:{
name: "King"
}
});
</script>
</body>
</html>
浏览器访问
- 首先通过 new Vue()来创建Vue实例
- 然后构造函数接收一个对象,对象中有一些属性:
- el:是element的缩写,通过id选中要渲染的页面元素,本例中是一个div
- data:数据,数据是一个对象,里面有很多属性,都可以渲染到视图中
- name:这里我们指定了一个name属性
- 页面中的
h1
元素中,我们通过{
{name}}的方式,来渲染刚刚定义的name属性。
双向绑定
<div id="app">
<input type="text" v-model="num"><button @click="num++">+</button>
<h1>
{
{name}} 很帅<br>
{
{num}}位女性为其着迷!
</h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data:{
name: "King",
num: 1
}
});
</script>
- 我们在data添加了新的属性:
num
- 在页面中有一个
input
元素,通过v-model
与num
进行绑定。 - 同时通过
{
在页面输出
{num}}
每次点击”+”,数值都会变化,比如我点了三次加号效果如下
注意:需要安装Vue Devtools才会有那个Vue视图
我们可以观察到,输入框的变化引起了data中的num的变化,同时页面输出也跟着变化。
- input与num绑定,input的value值变化,影响到了data中的num值
- 页面
{
与数据num绑定,因此num值变化,引起了页面效果变化。
{num}}
定义方法
前面vue中是定义了属性name和num,这里定义方法
页面添加按钮
//div中
<button @click="handleClick">快来点我</button>
//vue添加
const app = new Vue({
el: "#app",
data:{
name: "King",
num: 1
},
methods:{
handleClick(){
console.log("hello world!")
}
}
});
@click帮点了方法handleClick
点击按钮后控制台输出 hello world!
钩子函数
例如:created代表在vue实例创建后;我们可以在Vue中定义一个created函数,代表这个时期的构造函数:
const app = new Vue({
el: "#app",
data:{
name: "King",
num: 1
},
methods:{
handleClick(){
console.log("hello world!")
}
},
created(){
setTimeout(()=>this.name="King真的",1000)//this指向app
}
});
1秒后页面由 King很帅 变成了 King真的很帅。
v-text和v-html
说明:
- v-text:将数据输出到元素内部,如果输出的数据有HTML代码,会作为普通文本输出
- v-html:将数据输出到元素内部,如果输出的数据有HTML代码,会被渲染
使用{
{属性}}来输出存在一个问题,如果网速很慢,那么用户体验户会很不好,下面做个简单测试。
首先,浏览器进行网络设置,改为3G网,同时刷新的时候选择清空缓存并硬性加载
效果如下:
一段时间后恢复正常,但是用户看到这样的页面是非常不友好的,所以考虑使用v-text和v-html来替换。
<h1>
<span v-text="name"></span>很帅<br>
{
{num}}位女性为其着迷!<br>
<span v-html="name" style="color: red"></span>很帅<br>
</h1>
页面上就不会有那种不友好的展示了。
但是v-text和v-html有什么区别呢?我们将钩子函数修改以下
created(){
//setTimeout(()=>this.name="King真的",1000)//this指向app
this.name="<font style='color: red'>King真的</font>"
}
此时刷新页面查看
区别就不言而喻了。
v-model
刚才的v-text和v-html可以看做是单向绑定,数据影响了视图渲染,但是反过来就不行。接下来学习的v-model是双向绑定,视图(View)和模型(Model)之间会互相影响。
既然是双向绑定,一定是在视图中可以修改数据,这样就限定了视图的元素类型。目前v-model的可使用元素有:
- input
- select
- textarea
- checkbox
- radio
- components(Vue中的自定义组件)
基本上除了最后一项,其它都是表单的输入项。下面拿checkbox来举例
<h1>请挑选课程:</h1>
<input type="checkbox" value="Java" v-model="lessons">Java<br>
<input type="checkbox" value="C++" v-model="lessons">C++<br>
<input type="checkbox" value="Python" v-model="lessons">Python<br>
<h1>
挑选了以下课程:{
{lessons.join(",")}}
</h1>
//vue中data添加lessons属性
data:{
name: "King",
num: 1,
lessons:[]
},
- 多个
CheckBox
对应一个model时,model的类型是一个数组,单个checkbox值是boolean类型 - radio对应的值是input的value值
input
和textarea
默认对应的model是字符串select
单选对应字符串,多选对应也是数组
v-on与事件修饰符
v-on指令用于给页面元素绑定事件。
语法:
v-on:事件名="js片段或函数名"
注意:v-on:click之前是缩写成了@click,效果是一样的
<div style="width: 100px;height: 100px;background-color: red;" @click="print('div')">
<button @click="print('button')">点我试试</button>
</div>
//vue的方法中添加print方法
methods:{
handleClick(){
console.log("hello world!")
},
print(message){
console.log(message)
}
},
点击 “点我试试”按钮后,注意到同时输出了div和button,这是因为事件传播导致的,因为button是div的函数,点击了button就相当于点击了div,使用vue可以使用.stop阻止传播
<button @click.stop="print('button')">点我试试</button>
点击“点我试试”按钮后不再输出div
另外使用a标签的使用,使用@click.prevent可以阻止跳转
<a href="www.baidu.com" @click.prevent="print('百度')">百度以下,你就傻了!</a>
点击后并不会跳转到 www.baidu.com
v-for
v-for可以很简单的进行数组或者对象的遍历,添加属性users,下面先遍历数组后遍历对象
data:{
name: "King",
num: 1,
lessons:[],
users:[
{name:'柳岩', gender:'女', age: 21},
{name:'虎哥', gender:'男', age: 30},
{name:'范冰冰', gender:'女', age: 24},
{name:'刘亦菲', gender:'女', age: 18},
{name:'古力娜扎', gender:'女', age: 25}
],
},
使用v-for
<ul>
<li v-for="(u,i) in users">{
{i}} {
{u.name+","+u.gender+","+u.age}}</li>
</ul>
u取出数组中对象,i表示下标
再来遍历users中的第一个对象
<ul>
<li v-for="(val,key,idx) in users[0]">{
{idx}} {
{key+":"+val}}</li>
</ul>
甚至可以迭代数字
<ul>
<li v-for="i in 5">{
{i}}</li>
</ul>
注意是从1到5而不是0到4
v-if
很简单的使用if,对1-5进行奇偶数区分
<ul>
<li v-for="i in 5">
<span v-if="i%2==0">我是偶数:{
{i}}</span>
<span v-else style="color: red">我是奇数:{
{i}}</span>
</li>
</ul>
另外还有 “v-else-if”就不举例了。
v-show
v-show的作用跟v-if 是一样的,均是做条件判断
data中添加属性
show: true
v-show的使用,点击 “点我切换按钮”后show的值在true和false间切换
<button @click="show=!show">点我切换</button>
<h1 v-if="show">
Are you ok?
</h1>
<h1 v-show="show">
Are you ok?
</h1>
接着我们点击按钮,两个 “Are you ok”会消失,查看页面属性
代码
<h1 v-if="show">
Are you ok?
</h1>
直接擦除吊了,而带v-show的那部分成了 display:none,只是隐藏。也就是说不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS 属性 display
。
第一部分学完了,完整代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello vue</title>
</head>
<body>
<div id="app">
<!--vue的基本使用-->
<input type="text" v-model="num"><button @click="num++">+</button>
<h1>
<span v-text="name"></span>很帅<br>
{
{num}}位女性为其着迷!<br>
<span v-html="name" style="color: red"></span>很帅<br>
</h1>
<button @click="handleClick">快来点我</button>
<!--v-model-->
<h1>请挑选课程:</h1>
<input type="checkbox" value="Java" v-model="lessons">Java<br>
<input type="checkbox" value="C++" v-model="lessons">C++<br>
<input type="checkbox" value="Python" v-model="lessons">Python<br>
<h1>
挑选了以下课程:{
{lessons.join(",")}}
</h1>
<!--v-on-->
<div style="width: 100px;height: 100px;background-color: red;" @click="print('div')">
<button @click.stop="print('button')">点我试试</button>
<a href="www.baidu.com" @click.prevent="print('百度')">百度以下,你就傻了!</a>
</div>
<!--v-for-->
<ul>
<li v-for="(u,i) in users">{
{i}} {
{u.name+","+u.gender+","+u.age}}</li>
</ul>
<ul>
<li v-for="(val,key,idx) in users[0]">{
{idx}} {
{key+":"+val}}</li>
</ul>
<ul>
<li v-for="i in 5">{
{i}}</li>
</ul>
<!--v-if-->
<ul>
<li v-for="i in 5">
<span v-if="i%2==0">我是偶数:{
{i}}</span>
<span v-else style="color: red">我是奇数:{
{i}}</span>
</li>
</ul>
<button @click="show=!show">点我切换</button>
<h1 v-if="show">
Are you ok?
</h1>
<h1 v-show="show">
Are you ok?
</h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data:{
name: "King",
num: 1,
lessons:[],
users:[
{name:'柳岩', gender:'女', age: 21},
{name:'虎哥', gender:'男', age: 30},
{name:'范冰冰', gender:'女', age: 24},
{name:'刘亦菲', gender:'女', age: 18},
{name:'古力娜扎', gender:'女', age: 25}
],
show: true
},
methods:{
handleClick(){
console.log("hello world!")
},
print(message){
console.log(message)
}
},
created(){
//setTimeout(()=>this.name="King真的",1000)//this指向app
this.name="<font style='color: red'>King真的</font>"
}
});
</script>
</body>
</html>
v-bind与class属性绑定
假如我们想动态的修改页面元素的属性,比如class属性,这样写是错误的:
<div class="{
{isAcctive}}"></div>
因为插值表达式不能用在属性的值中。我们可以传给 v-bind:class
(可以简写为:class)一个对象,以动态地切换 class。新创建个html文件 ,完整代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello vue</title>
<style type="text/css">
div#box {
width: 100px;
height: 100px;
color: darkgray;
}
.red{
background-color: red;
}
.blue {
background-color: blue;
}
</style>
</head>
<body>
<div id="app">
<!--class属性-->
<button @click="isRed=!isRed">点我换颜色</button>
<div id="box" :class="{red:isRed,blue:!isRed}">
来看我的颜色
</div>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data:{
isRed: true
}
});
</script>
</body>
</html>
点击按钮后
计算属性
在插值表达式中使用js表达式是非常方便的,而且也经常被用到。
但是如果表达式的内容很长,就会显得不够优雅,而且后期维护起来也不方便,例如下面的场景,我们有一个日期的数据,但是是毫秒值:
data:{
birthday:1529032123201 // 毫秒值
}
我们在页面渲染,希望得到yyyy-MM-dd的样式:
<h1>您的生日是:{
{
new Date(birthday).getFullYear() + '-'+ new Date(birthday).getMonth()+ '-' + new Date(birthday).getDay()
}}
</h1>
虽然能得到结果,但是非常麻烦。Vue中提供了计算属性,来替代复杂的表达式:
<!--计算属性 定义的时候似乎是方法,实际上是属性-->
<h1>
我的生日是:{
{myBirth}}<br>
我的生日是:{
{myBirth}}<br>
我的生日是:{
{myBirth}}
</h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data:{
isRed: true,
birthday: 1345032504930,
},
computed:{//计算属性
myBirth(){
console.log("hello");
const day = new Date(this.birthday);
return day.getFullYear()+"年"+day.getMonth()+"月"+day.getDay()+"日";//需要返回
}
}
});
</script>
只输出了一次”hello”,说明这个方法其实只被调用了一次。
- 计算属性本质就是方法,但是一定要返回数据。然后页面渲染时,可以把这个方法当成一个变量来使用。
watch
watch可以让我们监控一个值的变化。从而做出相应的反应。
<input type="text" v-model="num">
<h1>num:{
{num}}</h1>
const app = new Vue({
el: "#app",
data:{
isRed: true,
birthday: 1345032504930,
num: 1
},
computed:{//计算属性
myBirth(){
console.log("hello");
const day = new Date(this.birthday);
return day.getFullYear()+"年"+day.getMonth()+"月"+day.getDay()+"日";//需要返回
}
},
watch:{
num(val,oldVal){
console.log(val,oldVal);
}
}
});
补充:深度监视?
const app = new Vue({
el: "#app",
data:{
isRed: true,
birthday: 1345032504930,
num: 1,
person:{
name:"Jack",
age:22
}
},
computed:{//计算属性
myBirth(){
console.log("hello");
const day = new Date(this.birthday);
return day.getFullYear()+"年"+day.getMonth()+"月"+day.getDay()+"日";//需要返回
}
},
watch:{
num(val,oldVal){
console.log(val,oldVal);
},
person:{//监视person对象的变化
deep:true,
handler(obj){
console.log(obj.age)
}
}
}
});
点击几次+号后控制台查看
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello vue</title>
<style type="text/css">
div#box {
width: 100px;
height: 100px;
color: darkgray;
}
.red{
background-color: red;
}
.blue {
background-color: blue;
}
</style>
</head>
<body>
<div id="app">
<!--class属性-->
<button @click="isRed=!isRed">点我换颜色</button>
<div id="box" :class="{red:isRed,blue:!isRed}">
来看我的颜色
</div>
<!--计算属性 定义的时候似乎是方法,实际上是属性-->
<h1>
我的生日是:{
{myBirth}}<br>
我的生日是:{
{myBirth}}<br>
我的生日是:{
{myBirth}}
</h1>
<!--watch-->
<input type="text" v-model="num"/>
<h1>
{
{num}}
</h1>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data:{
isRed: true,
birthday: 1345032504930,
num: 1,
person:{
name:"Jack",
age:22
}
},
computed:{//计算属性
myBirth(){
console.log("hello");
const day = new Date(this.birthday);
return day.getFullYear()+"年"+day.getMonth()+"月"+day.getDay()+"日";//需要返回
}
},
watch:{
num(val,oldVal){
console.log(val,oldVal);
},
person:{
deep:true,
handler(obj){
console.log(obj.age)
}
}
}
});
</script>
</body>
</html>
全局组件
在大型应用开发的时候,页面可以划分成很多部分。往往不同的页面,也会有相同的部分。例如可能会有相同的头部导航。
但是如果每个页面都独自开发,这无疑增加了我们开发的成本。所以我们会把页面的不同部分拆分成独立的组件,然后在不同页面就可以共享这些组件,避免重复开发。
我们通过Vue的component方法来定义一个全局组件。
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<div id="app"><!--使用全局组件 定义好的组件,可以任意复用多次:-->
<counter></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
// 定义全局组件,两个参数:1,组件名称。2,组件参数
Vue.component("counter",{
template:"<button @click='count++'>你点了我{
{count}}次</button>",
data(){
return {
count:0
}
}
});
const app = new Vue({
el:"#app"
});
</script>
</body>
</html>
点两次按钮后
- 组件其实也是一个Vue实例,因此它在定义时也会接收:data、methods、生命周期函数等
- 不同的是组件不会与页面的元素绑定,否则就无法复用了,因此没有el属性。
- 但是组件渲染需要html模板,所以增加了template属性,值就是HTML模板
- 全局组件定义完毕,任何vue实例都可以直接在HTML中通过组件名称来使用组件了。
- data的定义方式比较特殊,必须是一个函数。
局部组件
//局部组件
const v = {
template:"<button @click='count++'>你点了我{
{count}}次</button>",
data(){
return{
count:0
}
}
};
const app = new Vue({
el: "#app",
data:{
},
components: {//使用局部组件
counter:v
}
})
效果同上
完整代码如下:
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<div id="app">
<counter></counter>
</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
// 定义全局组件,两个参数:1,组件名称。2,组件参数
// Vue.component("counter",{
// template:"<button @click='count++'>你点了我{
{count}}次</button>",
// data(){
// return {
// count:0
// }
// }
// });
// const app = new Vue({
// el:"#app"
// });
//局部组件
const v = {
template:"<button @click='count++'>你点了我{
{count}}次</button>",
data(){
return{
count:0
}
}
};
const app = new Vue({
el: "#app",
data:{
},
components: {//使用局部组件
counter:v
}
})
</script>
</body>
</html>
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136072.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...