<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
npm install vue
若报错,先执行npm init -f ,再执行npm install vue
重要: GitHub 仓库的 /dist
文件夹只有在新版本发布时才会提交。如果想要使用 GitHub 上 Vue 最新的源码,需要自己构建!
git clone https://github.com/vuejs/vue.git node_modules/vue
cd node_modules/vue
npm install
npm run build
Vue 是一套用于构建用户界面的渐进式框架。
运行.vue文件
D:\workplace\vue>vue serve
易用: 会html、css、js即可上手
灵活: 不断繁荣的生态系统,可以在一个库和一套完整框架之间自如伸缩
高效: 20KB min + gzip 运行大小,超快虚拟DOM,最省心的优化
框架:是一套完整的解决方案,对项目的侵入性比较大,项目如果需要换框架,需重新搭建整个项目
库:提供一个小功能,对项目的入侵性比较小,如果某个库无法完成某些需求,可以很容易切换到其他库实现需求
引入vue
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
或者
<script src="https://cdn.jsdelivr.net/npm/vue">script>
里面可以放的东西
{{ 'a' }} 字符string
{{ 12 }} number
{{ true } 布尔值
{{ [1,2,3] }} 数组
{{ {a:1, b:10 } }} 对象object
{{ undefined }}
{{ null }}
{{ 1+1 }} 表达式
v-text会覆盖元素中原来的内容,但插值表达式只会替换自己的占位符不会把整个元素清空。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue测试title>
<script src="js/vue.js">script>
head>
<body>
<div id="app">
<p>+++{{msg}}---p>
<p v-text="msg">+++---p>
div>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: '123'
}
});
script>
body>
html>
+++123---
123
动态渲染的任意html可能会非常危险,很容易导致xss攻击
如:绑定图片:<img v-bind:src="imgUrl" v-bind:alt="name" /> 或者
<img :src="imgUrl" :alt="name" />
当图片出现错误的时候,会显示图片的name
特殊的:class、style
class:
1、绑定多个class用数组:<h4 :class="[h4Class, h4Width]">{{ name }}h4>
<h4 :class="[{red: true}, h4Width]">{{ name }}h4>
2、对象:<h4 :class="{red: true}">{{ name }}h4>
3、多元表达式:<h4 :class="[h4Flag ? 'red' : '' , h4Width]">{{ name }}h4>
style:
对象: <img :src="imgUrl" :alt="name" :style="{width: imgWidth, border: '10px solid red'}"/>
数组: <img :src="imgUrl" :alt="name" :style="[{width: imgwidth}, imgStyle]"/> <script> data: { imgStyle: {border: '10px solid red'} }script>
<button v-on:click="handleClick">点击button>
等价于 <button @click="handleClick">点击button>
.stop
:阻止事件冒泡(通俗讲就是阻止事件向上级DOM元素传递)
.prevent
:阻止默认事件(如:链接跳转、表单提交。。。)
.capture
:添加事件侦听器时使用事件捕获模式(执行事件捕获阶段,由外向内触发事件)
.self
:将事件绑定到自身,只有自身才能触发,通常用于避免冒泡事件的影响
.once
:设置事件只能触发一次,比如按钮的点击等。
.passive
:会执行默认方法
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,
用 v-on:click.prevent.self
会阻止所有的点击,
而 v-on:click.self.prevent
只会阻止对元素自身的点击。
<div id="app14">
<a href="https://www.baidu.com/" @click.prevent.once>baidua>
div>
<script src="../vue.js">script>
<script>
const app14 = new Vue({
el:'#app14',
data:{
}
});
script>
<div id="app15">
<div style="width: 300px; height: 300px;background-color: aqua" @click="outclick">
<div style="width: 200px; height: 200px;background-color: #855988" @click.self="innerclick">
<div style="width: 100px; height: 100px;background-color: #123456" @click="mostinnerclick">
div>
div>
div>
div>
div>
<script>
const app15 = new Vue({
el: '#app15',
methods: {
outclick() {
console.info('outer');
},
innerclick() {
console.info('inner');
},
mostinnerclick() {
console.info('mostinner');
}
}
})
script>
<button @click="handleClick">{{ text }}button>
<div class="box red" v-if="show">div>
data: {
show: true,
text: '隐藏'
},
methods: {
handleClick () {
this.show = !this.show;
this.text = this.show ? '隐藏' : '显示';
}
}
<button @click="handleClick">{{ text }}button>
<div class="box red" v-if="show">div>
<div class="box green" v-else>div>
<div class="box red" v-if="num === 0">div>
<div class="box yellow" v-else-if="num === 1">div>
<div class="box green" v-else>div>
data: {
show: true,
text: '隐藏',
num: 0
},
methods: {
handleClick () {
this.show = !this.show;
this.text = this.show ? '隐藏' : '显示';
}
}
<ul>
<li v-for="(item, index) in arr">{{ item }} --- {{ index }}li>
ul>
const vm = new Vue({
el: '#app',
data: {
arr: ['html', 'js', 'vue']
}
})
<h4 v-for="(value, key, index) in obj">{{ value }} --- {{key}} --- {{index}}h4>
const vm = new Vue({
el: '#app',
data: {
obj: {
name: 'yitian',
age: 18,
looks: 'beautiful'
}
}
})
key:name value:'yitian'
<p v-for="item in 10">{{ item }}p>
数字1到10打印出来
<div v-for="item in 'yitian'">{{ item }}div>
filter:过滤数组中某些元素,返回符合条件的元素组成的新数组
concat:合并两个或以上的数组,可以链式调用,返回合并后的数组
slice:切割数组中某一段元素,返回一个切割出来的数组
它们不会改变原始数组,而总是返回一个新数组
set方法还可以为对象添加属性和值
<script>
export default {
data(){
return {
obj:{
name:'xiaoming'
}
}
},
methods:{
change(){
this.$set(this.obj,'age',12)
console.log(this.obj);{name:xiaoming,age:12}
}
}
}
</script>
obj 需要定义属性的当前对象
prop 当前需要定义的属性名
value 属性描述符
<script>
export default {
data(){
return {
obj:{
name:'xiaoming'
}
}
},
methods:{
change(){
this.obj=Object.assign({},this.obj,{
height:180,
eq:200
})
}
}
}
</script>
<input type="text" v-model="value"/>
<span>{{ value }}span>
data: {
value: 'yitian'
}
<input type="checkbox" v-model="checked" />
{{ checked }}
data: {
checked: true
}
<label for="html" >htmllabel>
<input type="checkbox" value="html" id="html" v-model="checkedList"/>
<label for="js" >jslabel>
<input type="checkbox" value="js" id="js" v-model="checkedList"/>
<label for="vue" >vuelabel>
<input type="checkbox" value="vue" id="vue" v-model="checkedList"/>
{{ checkedList }}
data: {
checkedList: []
}
<label for="html">htmllabel>
<input type="radio" id="html" value="html" v-model="picked"/>
<label for="js">jslabel>
<input type="radio" id="js" value="js" v-model="picked"/>
<label for="vue">vuelabel>
<input type="radio" id="vue" value="vue" v-model="picked"/>
{{ picked }}
data: {
picked: ''
}
{{ selected }}
data: {
selected: ''
}
<select name="" id="" v-model="selectedList" multiple>
<option value="html">htmloption>
<option value="js">jsoption>
<option value="vue">vueoption>
select>
{{ selectedList }}
data: {
selectedList: ''
}
<textarea v-model="content">textarea>
{{ content }}
data: {
content: ''
}
{{ desc }}
{{ looks }}
data: {
name: '一天',
age: 24,
looks: 'handsome',
desc: '姓名: 一天 年龄: 24'
},
watch: {
name() {
this.desc = `姓名: ${this.name} 年龄: ${this.age}`;
}
}
data: {
name: '一天',
age: 24,
looks: 'handsome',
},
computed: {
desc () {
return `姓名: ${this.name} 年龄: ${this.age}`;
}
}
}
methods: 想要去写一些逻辑,比如说要去触发一个事件的时候,或者在某一个函数里面再去写另一个函数作为封装的时候
computed: 想要得到一个新的数据,而且拿过来就可以使用
watch: 当想要在某一个事件改变的时候,去做一个什么什么样的事情的时候
组件里的data()必须是一个函数
props 是你可以在组件上注册的一些自定义特性
局部注册的组件在其子组件中不可用
// 例如,如果你希望 ComponentA 在 ComponentB 中可用,则你需要这样写:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
<blog-post v-bind:likes="42">blog-post>
<blog-post v-bind:likes="post.likes">blog-post>
<blog-post is-published>blog-post>
<blog-post v-bind:is-published="false">blog-post>
<blog-post v-bind:is-published="post.isPublished">blog-post>
<blog-post v-bind:comment-ids="[234, 266, 273]">blog-post>
<blog-post v-bind:comment-ids="post.commentIds">blog-post>
<blog-post
v-bind:author="{
name: 'Veronica',
company: 'Veridian Dynamics'
}"
>blog-post>
<blog-post v-bind:author="post.author">blog-post>
注意在 JavaScript 中对象和数组是通过引用传入的,所以对于一个数组或对象类型的 prop 来说,在子组件中改变这个对象或数组本身将会影响到父组件的状态。
vue父子通讯是单向数据流,也就是子组件不能修改父组件的值,但是在很多情况下是需要这样做的,比如在做功能编辑的时候,子组件需要带入父组件的原始值,而且子组件也需要修改这个值,到最后的保存值中
//父组件将age传给子组件并使用.sync修饰符。
<MyFooter :age.sync="age">
</MyFooter>
//子组件触发事件
mounted () {
console.log(this.$emit('update:age',1234567));
}
update:是被固定的也就是vue为我们约定好的名称部分
age是我们要修改的状态的名称,是我们手动配置的,与传入的状态名字对应起来
注意带有 .sync
修饰符的 v-bind
不能和表达式一起使用
插槽就是子组件中的提供给父组件使用的一个占位符,用 表示,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充的内容会替换子组件的标签。
插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制
全局组件 局部组件
component
<div id="app">
<hello-world>hello-world>
<hello-world>hello-world>
<hello-world>hello-world>
div>
//Vue.component('组件的名字',{对象:组件的一些配置参数})
Vue.component('HelloWorld', {
//组件里的data()必须是一个函数
data() {
return {
msg: 'hello'
}
},
//组件的模版即结构
template: `
{{ msg }}
`,
methods: {
handleClick () {
this.msg = 'yitian';
}
}
})
const vm = new Vue({
el: '#app',
data: {
},
})
components
const vm = new Vue({
el: '#app',
data: {
},
components: {
'HelloWorld': {
template: `
hello
`
}
}
})
String
Number
Boolean
Array
Object
Date
Function
Symbol
自定义的构造函数
function Person (firstName, lastName) {
this.firstName = firstName
this.lastName = lastName
}
Vue.component('blog-post', {
props: {
author: Person
}
})
验证 author prop 的值是否是通过 new Person 创建的。
components: {
myContent: {
// props: ['title', 'content'],
// props属性校验
props: {
title: {
type: String,
// default:规定默认值
default: '山山水水'
},
content: {
type: Number,
required: true,//true为必传
validator (val){
// content传递的数>10000,不符合的话会报错
return val > 10000
}
},
number: {
type: Number
},
obj: {
type: Object
}
},
}
}
}
<div id="app">
<my-content v-bind="childrenInfo">my-content>
div>
const vm = new Vue({
el: '#app',
data: {
childrenInfo: {
title: '一天',
content: 78525,
number: 0,
obj: { a:1, b:10}
}
},
components: {
myContent: {
// props: ['title', 'content'],
// props属性校验
props: {
title: {
type: String,
// default:规定默认值,没有传title值的时候,会显示default值
default: '山山水水'
},
content: {
type: Number,
required: true,
validator (val){
return val > 10000
}
},
number: {
type: Number
},
obj: {
type: Object
}
},
data () {
return {
ownNumber: this.number
}
},
template: `
{{ title }}
{{ content }}
{{ ownNumber }}
{{ obj }}
`,
methods: {
handleClick() {
this.ownNumber ++;
// this.obj.a = 100;
}
}
}
}
})
直接子组件告诉父组件做什么,由父组件去做
<div id="app">
<my-content v-bind="childrenInfo" @add="handleAdd">my-content>
父组件内的number: {{ childrenInfo.number }}
<button @click="handleClick">点击button>
div>
const vm = new Vue({
el: '#app',
data: {
childrenInfo: {
title: '一天',
content: 78525,
number: 0,
obj: { a:1, b:10}
}
},
methods: {
handleAdd(num){
this.childrenInfo.number += num;
},
handleClick() {
this.childrenInfo.title = '是一天吖'
}
},
components: {
myContent: {
// props: ['title', 'content'],
// props属性校验
props: {
title: {
type: String,
// default:规定默认值
default: '山山水水'
},
content: {
type: Number,
required: true,
validator (val){
return val > 10000
}
},
number: {
type: Number
},
obj: {
type: Object
}
},
data () {
return {
// ownNumber: this.number
}
},
template: `
{{ title }}
{{ content }}
子组件内的number: {{ number }}
{{ obj }}
`,
methods: {
handleClick() {
// this.ownNumber += 10;
// 触发一个事件“add”
this.$emit('add', 10)
// this.obj.a = 100;
}
}
}
}
})
v-enter :定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。
v-enter-active:定义进入过渡生效时的状态在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
v-enter-to:定义进入过渡的结束状态在元素被插入之后下一帧生效(与此同时v-enter被移除),在过渡/动画完成之后移除。
v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
v-leave-to:定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave被删除),在过渡/动画完成之后移除。
<div id="app1">
<button @click="show = !show">
Toggle
button>
<transition name="fade">
<p v-if="show">yitianp>
transition>
div>
<script>
const app1 = new Vue({
el: '#app1',
data: {
show: true
}
})
script>
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
style>
<div id="app2">
<button @click="show = !show">
Toggle render
button>
<transition name="slide-fade">
<p v-if="show">hellop>
transition>
div>
<script>
const app2 = new Vue({
el: '#app2',
data: {
show: true
}
})
script>
<style>
/* 可以设置不同的进入和离开动画 */
/* 设置持续时间和动画函数 */
.slide-fade-enter-active {
transition: all .3s ease;
}
.slide-fade-leave-active {
transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
}
.slide-fade-enter, .slide-fade-leave-to
/* .slide-fade-leave-active for below version 2.1.8 */ {
transform: translateX(10px);
opacity: 0;
}
style>
<div id="app3">
<button @click="show = !show">Toggle showbutton>
<transition name="bounce">
<p v-if="show">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris facilisis enim libero, at lacinia diam fermentum id. Pellentesque habitant morbi tristique senectus et netus.p>
transition>
div>
<script>
const app3 = new Vue({
el: '#app3',
data: {
show: true
}
})
script>
<style>
.bounce-enter-active {
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
style>
结合第三方CSS库:animate.css
animate.css库使用方法:在官网(https://daneden.github.io/animate.css/)上找到合适的动画,如上方法添加指定的类名(必须带有"animated"类名)。
l
<link href="https://cdn.jsdelivr.net/npm/[email protected]" rel="stylesheet" type="text/css">
<div id="app4">
<button @click="show = !show">
Toggle render
button>
<transition
name="custom-classes-transition"
enter-active-class="animated tada"
leave-active-class="animated bounceOutRight"
>
<p v-if="show">hellop>
transition>
div>
<script>
const app4 = new Vue({
el: '#app4',
data: {
show: true
}
})
script>
同时使用过渡(transition)和动画(animation),可能存在时长不同,使用type特性并设置animation或transition来明确以哪个为市场标准。
<transition type="transition">...transition>
为标签添加具体持续时长
<transition :duration="1000">...transition>
<transition :duration="{ enter: 500, leave: 800 }">...transition>
⑦JS钩子函数
结合第三方JS动画库: Velocity.js
<script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js">script>
<div id="app5">
<button @click="show = !show"> Toggle button>
<transition
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
v-bind:css="false"
>
<p v-if="show"> Demo p>
transition>
div>
<script>
const app5 = new Vue({
el: '#app5',
data: {
show: false
},
methods: {
beforeEnter(el) {
el.style.opacity = 0
el.style.transformOrigin = 'left'
},
enter(el, done) {
Velocity(el, { opacity: 1, fontSize: '1.4em' }, { duration: 300 })
Velocity(el, { fontSize: '1em' }, { complete: done })
},
leave(el, done) {
Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 })
Velocity(el, { rotateZ: '100deg' }, { loop: 2 })
Velocity(el, {
rotateZ: '45deg',
translateY: '30px',
translateX: '30px',
opacity: 0
}, { complete: done })
}
}
})
script>
当只用 JavaScript 过渡的时候,在 enter 和 leave 中必须使用 done 进行回调。否则,它们将被同步调用,过渡会立即完成。
推荐对于仅使用 JavaScript 过渡的元素添加 v-bind:css=“false”,Vue 会跳过 CSS 的检测。这也可以避免过渡过程中 CSS 的影响。
Velocity.js 的具体用法请查看文档(http://www.mrfront.com/docs/velocity.js/index.html)。
是一个基于node.js的包管理器
npm -v
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install -g @vue/cli
cnpm install -g webpack
webpack 是 Javascript 打包器(module bundler)
<div id="app">
<square-change>square-change>
div>
.square-box {
width: 100px;
height: 100px;
margin-top: 20px;
border: 2px solid #ccc;
}
const vm = new Vue({
el: '#app',
data: {
},
components: {
squareChange: {
data() {
return {
colorArr: ['red', 'orange', 'yellow', 'green']
}
},
template: `
`,
methods: {
handleClick (color) {
// const color = e.target.dataset.color;
const squareBox = this.$refs.squareBox;
squareBox.style.backgroundColor = color;
}
}
}
}
})
<div id="app">
<square-change ref="cmp">square-change>
<button @click="handleClick">clickbutton>
div>
const vm = new Vue({
el: '#app',
data: {
},
methods: {
handleClick() {
console.log(this.$refs.cmp.colorArr);
}
},
components: {
squareChange: {
data() {
return {
colorArr: ['red', 'orange', 'yellow', 'green']
}
},
template: `
`,
methods: {
handleClick (color) {
// const color = e.target.dataset.color;
const squareBox = this.$refs.squareBox;
squareBox.style.backgroundColor = color;
}
}
}
}
})
cnpm install -g @vue/cli 安装脚手架,用于生成项目
cnpm install -g @vue/cli-service-global 快速原型开发 编译.vue文件
vue --version 查看vue-cli版本
运行.vue文件命令:
D:\workplace\vue>vue serve App.vue
//App.vue
//Progress.vue
{{ percentage }}%
//App.vue
线性进度条 --- 百分比外显
线性进度条 --- 百分比内显
//Progress.vue
{{ percentage }}%
在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用
完成实例初始化,初始化非响应式变量,元素DOM和数据都还没有初始化
this指向创建的实例
可以在这加个loading事件
data computed watch methods上的方法和数据均不能访问
在实例创建完成后被立即调用。
在这一步,实例已完成以下配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调
然而,挂载阶段还没开始,$el属性目前不可见
实例创建完成
完成数据(data props computed)的初始化,导入依赖项
可访问data computed watch methods上的方法和数据
未挂载DOM,不能访问$el,$ref为空数组
可在这结束loading,还能做一些初始化,实现函数自执行
可以对data数据进行操作,可进行一些请求,但由于DOM未挂载,请求过多或者占用时间过长会导致页面线上空白。
若在此阶段进行的DOM操作一定要放在Vue.nextTick()的回调函数中
在挂载开始之前被调用:相关的渲染函数首次被调用
有了el,编译了template/outerHTML
能找到对应的template,并编译完成render函数
el属性:检查vue配置,即new Vue{}里面的el项是否存在,有就继续检查template项,没有则等到手动绑定调用vm.$mount()
template: 检查配置中的template项,如果没有template进行填充被绑定区域,则被绑定区域的el对象的outerHTML(即整个#app DOM对象,包括和标签)都作为被填充对象替换掉填充区域
el 被新创建的 vm.$el 替换,挂载成功
完成创建vm.$el,和双向绑定
完成挂载DOM和渲染,可在mounted钩子对挂载的dom进行操作
即有了DOM且完成了双向绑定,可访问DOM节点,$ref
可在这发起后端请求,拿回数据,配合路由钩子做一些事情
可对DOM进行操作
数据更新时调用
数据更新之前
可在更新前访问现有的DOM,如手动移除天价的事件监听器
组件 DOM 已经更新,组件更新完毕
完成虚拟DOM的重新渲染和打补丁
组件DOM已完成更新
可执行依赖的DOM操作
注意:不要在此函数中操作数据,会陷入死循环
在使用vue-router时,有时需要使用 来缓存组件状态,这个时候created钩子就不会被重复调用了
如果子组件需要在每次加载的时候进行某些操作,可以使用activated钩子触发
for keep-alive 组件被移除时使用
在执行app.$destroy()之前
可做一些删除提示,如:您确认删除xx吗?
可用于销毁定时器,解绑全局时间,销毁插件对象
当前组件已被删除,销毁监听事件 组件 事件子实例也被销毁
这时组件已经没有了,无法操作里面的任何东西
C:\Users\Admin>D:
D:\>cd workplace
D:\workplace>vue create vue-app
D:\workplace>"node" "D:\nodejs\node_cache\\node_modules\@vue\cli\bin\vue.js" create vue-app
? Your connection to the default npm registry seems to be slow.
Use https://registry.npm.taobao.org for faster installation? Yes
Vue CLI v3.12.0
? Please pick a preset: Manually select features
? Check the features needed for your project: Babel
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In package.json
? Save this as a preset for future projects? Yes
? Save preset as: onlyBable
C:\Users\Admin>vue ui
创建 => 在此创建新项目 => 编辑信息之后,下一步 => 选择手动 => 功能界面,选择 Bable => 下一步,创建项目,不保留预设