https://cn.vuejs.org/
Vue官网传送门
el : 指定dom标签容器的选择器
data : 指定初始化状态数据的对象/函数(返回一个对象)
我这里展示一个表单的数据绑定 v-model
<html lang="en">
<head>
<meta charset="UTF-8">
<title>01_HelloWorldtitle>
head>
<body>
<div id="test">
<input type="text" v-model="msg"><br>
<input type="text" v-model="msg">
<p>hello {
{msg}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
const vm = new Vue({
// 配置对象 options
// 配置选项(option)
el: '#test', // element: 指定用vue来管理页面中的哪个标签区域
data: {
msg: '戏子666'
}
})
script>
body>
html>
直接在Google浏览器搜vue.js devtools下载
低偶性
可复用性
独立开发
可测试
View层展现的不是Mode层的数据,而是ViewModel的数据,由ViewModel负责与Model层交互,这就完全解耦了View层和Model层,这个解耦至关重要,它是前后端分离方案实施的重要一环。
MVVM模式的实现者
Model: 模型层,在这里表示JavaScript对象
View:视图层,在这里表示DOM (HTML操作的元素)
ViewModel:连接视图和数据的中间件,Vue.js就是MVVM中的ViewModel层的实现者
ViewModel就是定义了一个Observer观察者
ViewModel能够观察到数据的变化,并对视图对应的内容进行更新
ViewModel能够监听到视图的变化,并能够通知数据发生改变
el
指定dom标签容器的选择器,Vue就会管理对应的标签及其子标签
data
对象或函数类型,指定初始化状态属性数据的对象,vm也会自动拥有data中所有属性,页面中可以直接访问使用,数据代理: 由vm对象来代理对data中所有属性的操作(读/写)
methods
包含多个方法的对象,供页面中的事件指令来绑定回调,回调函数默认有event参数, 但也可以指定自己的参数所有的方法由vue对象来调用, 访问data中的属性直接使用this.xxx
computed
包含多个方法的对象,对状态属性进行计算返回一个新的数据, 供页面获取显示,一般情况下是相当于是一个只读的属性,利用set/get方法来实现属性数据的计算读取, 同时监视属性数据的变化,如何给对象定义get/set属性,
在创建对象时指定: get name () {
return xxx} / set name (value) {
}
对象创建之后指定: Object.defineProperty(obj, age, {
get(){
}, set(value){
}})
xxx: function(value){
}
xxx : {
deep : true,
handler : fun(value)
}
另一种添加监视方式:
vm.$watch('xxx', function(value){
})
v-text/v-html: 指定标签体
* v-text : 当作纯文本 更新元素的 textContent
* v-html : 将value作为html标签来解析 更新元素的 innerHTML
v-if v-else v-show: 显示/隐藏元素
* v-if : 如果vlaue为true, 当前标签会输出在页面中
* v-else : 与v-if一起使用, 如果value为false, 将当前标签输出到页面中
* v-show: 就会在标签中添加display样式, 如果vlaue为true, display=block, 否则是none
v-for : 遍历
* 遍历数组 : v-for="(person, index) in persons"
* 遍历对象 : v-for="value in person"
v-on : 绑定事件监听
* v-on:事件名, 可以缩写为: @事件名
* 监视具体的按键: @keyup.keyCode @keyup.enter
* 停止事件的冒泡和阻止事件默认行为: @click.stop @click.prevent
* 隐含对象: $event
v-bind : 强制绑定解析表达式
* html标签属性是不支持表达式的, 就可以使用v-bind
* 可以缩写为: :id='name'
* :class
* :class="a"
* :class="{classA : isA, classB : isB}"
* :class="[classA, classB]"
* :style
:style="{color : color}"
v-model
* 双向数据绑定
* 自动收集用户输入数据
ref : 标识某个标签,为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象
* ref='xxx'
* 读取得到标签对象: this.$refs.xxx
v-cloak : 使用它防止闪现表达式, 与css配合: [v-cloak] {
display: none }
测试vue内置指令案例
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板语法title>
head>
<body>
<div id="app">
<h2>1. 双大括号表达式h2>
<p>{
{content}}p>
<p>{
{content.toUpperCase()}}p>
<p v-text="msg">p>
<p v-html="msg">p>
<h2>2. 指令一: 强制数据绑定h2>
<a href="http://www.baidu.com">访问指定站点a><br>
<a v-bind:href="url">访问指定站点2a><br>
<a :href="url">访问指定站点2a><br>
<h2>3. 指令二: 绑定事件监听h2>
<button v-on:click="test">点我button>
<button @click="test">点我button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#app',
data: {
content: 'xizi6666666',
url: 'http://www.baidu.com',
msg: '百度'
},
methods: {
test () {
alert('你点个锤子!!!')
}
}
})
script>
body>
html>
getter: 属性的get方法
setter: 属性的set方法
测试计算属性的监视案例
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性和监视title>
head>
<body>
<div id="demo">
姓: <input type="text" placeholder="First Name" v-model="firstName"><br>
名: <input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向): <input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名2(单向): <input type="text" placeholder="Full Name2" v-model="fullName2"><br>
姓名3(双向): <input type="text" placeholder="Full Name3" v-model="fullName3"><br>
<p>{
{fullName1}}p>
<p>{
{fullName1}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
const vm = new Vue({
el: '#demo',
data: {
firstName: '戏',
lastName: '子',
fullName2: '戏-子'
},
//初始化显示/相关的data属性数据发送变化
// 计算属性配置: 值为对象
computed: {
fullName1 () {
// 属性的get()
console.log('fullName1()', this)
return this.firstName + '-' + this.lastName
},
fullName3: {
// 1. 你定义的 2.你没有调用 3,最终它执行了
//1.什么时候调用 2.用来做什么
//回调函数 计算并返回当前属性的值
get () {
console.log('fullName3 get()')
return this.firstName + '-' + this.lastName
},
// 当属性值发生了改变时自动调用, 监视当前属性值变化, 同步更新相关的其它属性值
set (value) {
// fullName3的最新value值
console.log('fullName3 set()', value)
// 更新firstName和lastName
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
watch: {
// 配置监视firstName属性
//firstName发送改变 函数调用
firstName: function (value) {
// 相当于属性的set
console.log('watch firstName', value)
// 更新fullName2 this就是vm对象(VUE实列对象)
this.fullName2 = value + '-' + this.lastName
}
}
})
// 监视lastName
vm.$watch('lastName', function (value) {
console.log('$watch lastName', value)
// 更新fullName2
this.fullName2 = this.firstName + '-' + value
})
script>
body>
html>
测试Class 与 Style 绑定
<html lang="en">
<head>
<meta charset="UTF-8">
<title>class与style绑定title>
<style>
.classA {
color: red;
}
.classB {
background: blue;
}
.classC {
font-size: 20px;
}
style>
head>
<body>
<div id="demo">
<h2>1. class绑定: :class='xxx'h2>
<p :class="myClass">xxx是字符串p>
<p :class="{classA: hasClassA, classB: hasClassB}">xxx是对象p>
<p :class="['classA', 'classB']">xxx是数组p>
<h2>2. style绑定h2>
<p :style="{
color:activeColor, fontSize}">:style="{ color: activeColor, fontSize: fontSize + 'px' }"p>
<button @click="update">更新button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
myClass: 'classA',
hasClassA: true,
hasClassB: false,
activeColor: 'red',
fontSize: '20px'
},
methods: {
update () {
this.myClass = 'classB'
this.hasClassA = !this.hasClassA
this.hasClassB = !this.hasClassB
this.activeColor = 'yellow'
this.fontSize = '30px'
}
}
})
script>
body>
html>
测试条件渲染
<html lang="en">
<head>
<meta charset="UTF-8">
<title>条件渲染title>
head>
<body>
<div id="demo">
<p v-if="ok">戏子测试if成功p>
<p v-else>戏子测试if失败p>
<hr>
<p v-show="ok">戏子测试show成功p>
<p v-show="!ok">戏子测试show失败p>
<button @click="ok=!ok">切换button>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
ok: true,
}
})
script>
body>
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>06_列表渲染title>
head>
<body>
<div id="demo">
<h2>测试: v-for 遍历数组h2>
<ul>
<li v-for="(p, index) in persons" :key="index">
{
{index}}--{
{p.name}}--{
{p.age}}
--<button @click="deleteP(index)">删除button>
--<button @click="updateP(index, {name:'Cat', age: 16})">更新button>
li>
ul>
<button @click="addP({name: 'xfzhang', age: 18})">添加button>
<h2>测试: v-for 遍历对象h2>
<ul>
<li v-for="(item, key) in persons[1]" :key="key">{
{key}}={
{item}}li>
ul>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
persons: [
{
name: 'Tom', age:18},
{
name: 'Jack', age:17},
{
name: 'Bob', age:19},
{
name: 'Mary', age:16}
]
},
methods: {
deleteP (index) {
//splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
this.persons.splice(index, 1) // 调用了不是原生数组的splice(), 而是一个变异(重写)方法
// 1. 调用原生的数组的对应方法
// 2. 更新界面
},
updateP (index, newP) {
console.log('updateP', index, newP)
// this.persons[index] = newP // vue根本就不知道
//删除index位置元素 新的元素代替
this.persons.splice(index, 1, newP)
// this.persons = []
},
addP (newP) {
this.persons.push(newP)
}
}
})
script>
body>
html>
测试列表渲染_过滤与排序
<html lang="en">
<head>
<meta charset="UTF-8">
<title>06_列表渲染_过滤与排序title>
head>
<body>
<div id="demo">
<input type="text" v-model="searchName">
<ul>
<li v-for="(p, index) in filterPersons" :key="index">
{
{index}}--{
{p.name}}--{
{p.age}}
li>
ul>
<div>
<button @click="setOrderType(2)">年龄升序button>
<button @click="setOrderType(1)">年龄降序button>
<button @click="setOrderType(0)">原本顺序button>
div>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
searchName: '',
orderType: 0, // 0代表不排序, 1代表降序, 2代表升序
persons: [
{
name: 'Tom', age:18},
{
name: 'Jack', age:17},
{
name: 'Bob', age:19},
{
name: 'Mary', age:16}
]
},
computed: {
filterPersons () {
// debugger
// 取出相关数据 相关属性发生变化 计算函数执行
const {
searchName, persons, orderType} = this
// ... 将一个数组转为用逗号分隔的参数序列。
let arr = [...persons]
// 过滤数组
if(searchName.trim()) {
arr = persons.filter(p => p.name.indexOf(searchName)!==-1)
}
// 排序
if(orderType) {
arr.sort(function (p1, p2) {
if(orderType===1) {
// 降序
return p2.age-p1.age
} else {
// 升序
return p1.age-p2.age
}
})
}
return arr
}
},
methods: {
setOrderType (orderType) {
this.orderType = orderType
}
}
})
script>
body>
html>
v-on:xxx="fun"
@xxx="fun"
@xxx="fun(参数)"
默认事件形参: event
隐含属性对象: $event
.prevent : 阻止事件的默认行为 event.preventDefault()
.stop : 停止事件冒泡 event.stopPropagation()
.keycode : 操作的是某个keycode值的健
.enter : 操作的是enter键
测试事件处理的案列
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件处理title>
head>
<body>
<div id="example">
<h2>1. 绑定监听h2>
<button @click="test1">test1button>
<button @click="test2('abc')">test2button>
<button @click="test3('abcd', $event)">test3button>
<h2>2. 事件修饰符h2>
<a href="http://www.baidu.com" @click.prevent="test4">百度一下a>
<div style="width: 200px;height: 200px;background: red" @click="test5">
<div style="width: 100px;height: 100px;background: blue" @click.stop="test6">div>
div>
<h2>3. 按键修饰符h2>
<input type="text" @keyup.13="test7">
<input type="text" @keyup.enter="test7">
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#example',
data: {
},
methods: {
test1(event) {
alert(event.target.innerHTML)
},
test2 (msg) {
alert(msg)
},
test3 (msg, event) {
alert(msg+'---'+event.target.textContent)
},
test4 () {
alert('点击了链接')
},
test5 () {
alert('out')
},
test6 () {
alert('inner')
},
test7 (event) {
console.log(event.keyCode)
alert(event.target.value)
}
}
})
script>
body>
html>
测试表单输入绑定
<html lang="en">
<head>
<meta charset="UTF-8">
<title>08_表单输入绑定title>
head>
<body>
<div id="demo">
<form action="/xxx" @submit.prevent="handleSubmit">
<span>用户名: span>
<input type="text" v-model="username"><br>
<span>密码: span>
<input type="password" v-model="pwd"><br>
<span>性别: span>
<input type="radio" id="female" value="女" v-model="sex">
<label for="female">女label>
<input type="radio" id="male" value="男" v-model="sex">
<label for="male">男label><br>
<span>爱好: span>
<input type="checkbox" id="basket" value="basket" v-model="likes">
<label for="basket">篮球label>
<input type="checkbox" id="foot" value="foot" v-model="likes">
<label for="foot">足球label>
<input type="checkbox" id="pingpang" value="pingpang" v-model="likes">
<label for="pingpang">乒乓label><br>
<span>城市: span>
<select v-model="cityId">
<option value="">未选择option>
<option :value="city.id" v-for="(city, index) in allCitys" :key="city.id">{
{city.name}}option>
select><br>
<span>介绍: span>
<textarea rows="10" v-model="info">textarea><br><br>
<input type="submit" value="注册">
form>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
username: '',
pwd: '',
sex: '男',
likes: ['foot'],
allCitys: [{
id: 1, name: '江西'}, {
id: 2, name: '上海'}, {
id: 3, name: '北京'}],
cityId: '2',
info: ''
},
methods: {
handleSubmit () {
console.log(this.username, this.pwd, this.sex, this.likes, this.cityId, this.info)
alert('提交注册的ajax请求')
}
}
})
script>
body>
html>
* beforeCreate()
* created()
* beforeMount()
* mounted()
* beforeUpdate()
* updated()
* beforeDestory()
* destoryed()
created()/mounted(): 发送ajax请求, 启动定时器等异步任务
beforeDestory(): 做收尾工作, 如: 清除定时器
测试Vue生命周期案列
<html lang="en">
<head>
<meta charset="UTF-8">
<title>_Vue实例_生命周期title>
head>
<body>
<div id="test">
<button @click="destroyVue">destory vuebutton>
<p v-if="isShow">戏子学Vuep>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#test',
data: {
isShow: true
},
beforeCreate() {
console.log('beforeCreate()')
},
created() {
console.log('created()')
},
beforeMount() {
console.log('beforeMount()')
},
mounted () {
//初始化显示之后立即调用(1次)
console.log('mounted()')
// 执行异步任务
//this.intervalId 是 setInterval() 返回的 ID 值。
//setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
this.intervalId = setInterval(() => {
console.log('-----')
this.isShow = !this.isShow
}, 1000)
},
beforeUpdate() {
console.log('beforeUpdate()')
},
updated () {
console.log('updated()')
},
beforeDestroy() {
console.log('beforeDestroy()')
// 执行收尾的工作
//clearInterval() 方法的参数必须是由 setInterval() 返回的 ID 值。
clearInterval(this.intervalId)
},
destroyed() {
console.log('destroyed()')
},
methods: {
destroyVue () {
this.$destroy()
}
}
})
script>
body>
html>
过渡+动画的案列测试
<html lang="en">
<head>
<meta charset="UTF-8">
<title>10_过渡&动画1title>
<style>
/*指定过渡样式*/
.xxx-enter-active, .xxx-leave-active {
transition: opacity 1s
}
/*指定隐藏时的样式*/
.xxx-enter, .xxx-leave-to {
opacity: 0;
}
.move-enter-active {
transition: all 1s
}
.move-leave-active {
transition: all 3s
}
.move-enter, .move-leave-to {
opacity: 0;
transform: translateX(20px)
}
.bounce-enter-active {
animation: bounce-in 1s;
}
.bounce-leave-active {
animation: bounce-in 1s reverse;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
/*0.5秒放大1.5倍*/
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
style>
head>
<body>
<div id="demo">
<button @click="show = !show">Togglebutton>
<transition name="xxx">
<p v-show="show">hellop>
transition>
div>
<hr>
<div id="demo2">
<button @click="show = !show">Toggle2button>
<transition name="move">
<p v-show="show">hellop>
transition>
div>
<hr>
<div id="example-2">
<button @click="show = !show">Toggle showbutton>
<br>
<transition name="bounce">
<p v-if="show" style="display: inline-block;background: red">戏子666p>
transition>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript">
new Vue({
el: '#demo',
data: {
show: true
}
})
new Vue({
el: '#demo2',
data: {
show: true
}
})
new Vue({
el: '#example-2',
data: {
show: true
}
})
script>
body>
html>
功能: 对要显示的数据进行特定格式化后再显示
注意: 并没有改变原本的数据, 可是产生新的对应的数据
Vue.filter(filterName, function(value[,arg1,arg2,...]){
// 进行一定的数据处理
return newValue
})
<div>{
{
myData | filterName}}</div>
<div>{
{
myData | filterName(arg)}}</div>
用过滤器对当前时间进行指定格式显示案列
<html lang="en">
<head>
<meta charset="UTF-8">
<title>11_过滤器title>
head>
<body>
<div id="test">
<h2>显示格式化的日期时间h2>
<p>{
{time}}p>
<p>最完整的: {
{time | dateString}}p>
<p>年月日: {
{time | dateString('YYYY-MM-DD')}}p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.22.1/moment.js">script>
<script>
// 定义过滤器
Vue.filter('dateString', function (value, format='YYYY-MM-DD HH:mm:ss') {
return moment(value).format(format);
})
new Vue({
el: '#test',
data: {
time: new Date()
},
//页面加载完执行这个
mounted () {
setInterval(() => {
this.time = new Date()
}, 1000)
}
})
script>
body>
html>
常用内置指令
v:text : 更新元素的 textContent
v-html : 更新元素的 innerHTML
v-if : 如果为true, 当前标签才会输出到页面
v-else: 如果为false, 当前标签才会输出到页面
v-show : 通过控制display样式来控制显示/隐藏
v-for : 遍历数组/对象
v-on : 绑定事件监听, 一般简写为@
v-bind : 强制绑定解析表达式, 可以省略v-bind
v-model : 双向数据绑定
ref : 为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象
v-cloak : 使用它防止闪现表达式, 与css配合: [v-cloak] {
display: none }
Vue.directive('my-directive', function(el, binding){
el.innerHTML = binding.value.toupperCase()
})
directives : {
'my-directive' : {
bind (el, binding) {
el.innerHTML = binding.value.toupperCase()
}
}
}
<div v-my-directive='xxx'>
自定义2个指令案列
12_指令_自定义指令
插件通常用来为 Vue 添加全局功能。
<html lang="en">
<head>
<meta charset="UTF-8">
<title>17_插件title>
head>
<body>
<div id="test">
<p v-my-directive="msg">p>
div>
<script type="text/javascript" src="../js/vue.js">script>
<script type="text/javascript" src="vue-myPlugin.js">script>
<script type="text/javascript">
// 声明使用插件(安装插件: 调用插件的install())
Vue.use(MyPlugin) // 内部会调用插件对象的install()
const vm = new Vue({
el: '#test',
data: {
msg: '戏子'
}
})
// 全局方法或属性
Vue.myGlobalMethod()
// 实例方法
vm.$myMethod()
new Object()
script>
body>
html>
vue自定义插件 vue_myplugin.js
(function (window) {
const MyPlugin = {
}
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或属性
Vue.myGlobalMethod = function () {
console.log('Vue函数对象的myGlobalMethod()')
}
// 2. 添加全局资源
Vue.directive('my-directive',function (el, binding) {
el.textContent = 'my-自定义插件----'+binding.value
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function () {
console.log('vm $myMethod()')
}
}
//向外暴露
window.MyPlugin = MyPlugin
})(window)