提示:阅读本章之前,请先阅读目录
Vue.js 2.0 最基础的内容,笔记
vue3: https://github.com/Panyue-genkiyo/vue3-learning
vue2依据脚手架:https://github.com/Panyue-genkiyo/vue-advance
vue基础不依赖脚手架:https://github.com/Panyue-genkiyo/vue-learning
我们通过引入Vue.js,就实现最简单的使用vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
Hello world!
<script type="text/javascript">
Vue.config.productionTip = false;
</script>
</body>
</html>
通过设置,Vue.config.productionTip = false;
来控制,控制台的提示,这个提示,是指生产环境,最好使用生产版本的vue
通过new Vue()来实例化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="root">
<h1>My Name: {{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 实例化
const x = new Vue({
"el": "#root",
"data": {
"name": "smobee"
}
});
</script>
</body>
</html>
我是在Visual Studio Code 启动的,Open With Live Server,所以,就是带有端口号的访问页面
我们可以通过按住Shift+刷新,强制刷新,就可以看到这个报错
如果,我们是直接以文件绝对路径访问,则不存在这个问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="root">
<h1>My Name: {{name}}</h1>
<h1>Now Time: {{Date.now()}}</h1>
<h1>Add: {{1+1}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 实例化
const x = new Vue({
"el": "#root",
"data": {
"name": "smobee"
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="root">
<h1>My Name: {{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 实例化
const x = new Vue({
"el": "#root",
"data": {
"name": "smobee"
}
});
const x1 = new Vue({
"el": "#root",
"data": {
"name": "xmfboss"
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div class="root">
<h1>My Name: {{name}}</h1>
</div>
<div class="root">
<h1>My Name: {{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 实例化
const x = new Vue({
"el": ".root",
"data": {
"name": "smobee"
}
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello</title>
<script type="text/javascript" src="./vue.js"></script>
</head>
<body>
<div id="root">
<h1>My Name: {{name}}</h1>
<input type="text" v-bind:value="comment">
<!-- 简写 -->
<input type="text" :value="result">
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
// 实例化
const x = new Vue({
"el": "#root",
"data": {
"name": "smobee",
"comment": "hello, smobee",
"result": 123456
}
});
</script>
</body>
</html>
const v = new Vue({
// 这是第一种写法,注释掉了
// el: "#root",
data: {
name: "test"
}
})
// 这是第二种写法
v.$mount("#root")
第一种
new Vue({
el: "#root",
data: {
name: "hello"
}
})
第二种
new Vue({
el: "#root",
data: function(){
// 这里的this,是vue实例本身
console.log(this)
return {
name: "hello"
}
}
})
第二种简写
new Vue({
el: "#root",
data(){
// 这里的this,是vue实例本身
console.log(this)
return {
name: "hello"
}
}
})
错误示范,如果使用箭头函数,this会是window实例
new Vue({
el: "#root",
data: () => {
// 这里的this,是vue实例本身
console.log(this)
return {
name: "hello"
}
}
})
let number = 100;
let person = {
name: "xiaofeng",
sex: "man"
}
Object.defindProperty(person, 'age', {
value: number,
enumberable: true, // 控制是否可被遍历(枚举)
writable: true, // 控制是否可被修改
configurable: true, // 控制是否可被删除
get: function() {
console.log("有人正在读取我")
return number
},
set(val){
console.log("有人正在设置我的值是:", value)
}
})
<button v-on:click="onClickOpen">我是按钮1</button>
<button v-on:click="onClickClose("hello", $event)">我是按钮1</button>
const vm = new Vue({
el: "#root",
data: {
name: "hello",
onClickEdit() {
console.log("其实我放到这里,也可以调用,只不过会使用数据代理的方式")
}
},
methods: {
onClickOpen(event) {
console.log("这里的this就是vm本身", this === vm)
console.log("这里的event,是元素本身", event)
console.log("我可以输出按钮的文字", evnet.innertText)
},
onClickClose(str, evnet) {
console.log("我传递了一个字符串", str)
console.log("我可以把event传递进来", event)
},
onClickTest: (event) => {
console.log("这里的event,箭头函数,是window对象", event)
}
}
})
prevent:阻止默认事件
stop:阻止冒泡
once:只执行一次
capture:使用事件的捕获模式
self:只有event.target是自己的时候,才会触发
passive:事件的默认,立即执行,无需等待事件回调后执行
<a href="baidu.com" @click.prevent="open">prevent 只执行click事件</a>
<div @click="open">
<p @click.stop="open">我是里面,阻止了冒泡,不会影响外面</p>
</div>
<div @click="open">
<a href="baidu.com" @click.stop.prevent="open">我是里面,阻止了冒泡,并组织默认事件</a>
</div>
<button @click.once="open">我只会被调用一次哦</butoon>
<div @click.self="open">
只有event.target是外面的元素,才会触发click
<p @click="open">我是里面</p>
</div>
scroll,是滚动条,响应事件,键盘上下滑动和鼠标滚轮,就会触发onClick事件
<ul @scroll="onClick">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
开启了passive之后,会先滚动滚动条,如果没有开启,会等onClick执行完后才会滚动滚动条
<ul @wheel.passive="onClick">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
onClick() {
for (int i = 0; i < 100000; i++) {
console.log(i)
}
}
// keyup是指,按键按下并放开
<input type="text" @keyup="onClick"></input>
// keydown是指,按键按下就触发
<input type="text" @keydown="onClick"></input>
// 示例
<input type="text" @keyup.enter="onClick"></input>
<input type="text" @keyup.Enter="onClick"></input>
<input type="text" @keyup.esc="onClick"></input>
<input type="text" @keyup.space="onClick"></input>
<input type="text" @keyup.delete="onClick"></input>
<input type="text" @keyup.up="onClick"></input>
<input type="text" @keyup.down="onClick"></input>
<input type="text" @keyup.left="onClick"></input>
<input type="text" @keyup.right="onClick"></input>
// tab比较特殊,因为会移出焦点
<input type="text" @keydown.tap="onClick"></input>
// 两个单词组成的,要用-隔开
<input type="text" @keyup.caps-lock="onClick"></input>
// 系统按键,需要搭配第二键使用
<input type="text" @keyup.ctrl="onClick">同时按下ctrl+其他按键,并放开</input>
<input type="text" @keyup.alt="onClick"></input>
<input type="text" @keyup.shift="onClick"></input>
<input type="text" @keyup.meta="onClick">win键</input>
// 小提示,组合键的
<input type="text" @keyup.ctrl.y="onClick">同时按下ctrl+y,并放开</input>
// 还可以自定义名称
Vue.config.keyCodes.huichejian = 13
onClick(e) {
// 输出当前按键的编码
console.log(e.keyCode)
if (e.keyCode === 13) {
console.log("回车键")
}
console.log("当前输入框的value值", e.target.value)
}
// 计算属性,更新数据的情况:
// 1. 首次加载
// 2. 依赖的数据发生了变化,计算属性也会重新计算一次
// 底层原理,是用了Object.defindProperty的getter和setter方法
<div>{{fullname}}</div>
const vm = Vue({
el: "#root",
data: {
name: "A",
name2: "B"
},
computed: {
fullname: {
get(){
return this.name + this.name2
},
set(){
console.log("有人想改我的值")
}
}
// 简写,只实现get
fullname() {
return this.name + this.name2
}
}
})
<span>{{message}}</span>
<div @click="isValue = !isValue">测试</div>
<div @click="onChangeValue">测试</div>
<div @click="window.alert("我可以用此方法,调用window参数")">测试</div>
const vm = Vue({
el: "#root",
data: {
isValue: true,
window
},
computed: {
message() {
return isValue ? "A" : "B"
}
},
methods: {
onChangeValue() {
this.isValue = !this.isValue
}
}
})
const vm = Vue({
el: "#root",
data: {
name: "123"
},
computed: {
newName() {
return this.name + '123'
}
},
watch: {
name: {
// 第一次会自动调用一次
immediate: true,
handler(newValue, oldValue) {
console.log("我被改变了", newValue, oldValue)
}
},
newName: {
// 我也可以同样监听计算属性
immediate: true,
handler(newValue, oldValue) {
console.log("我被改变了", newValue, oldValue)
}
},
// 简写
newName(newValue, oldValue) {
console.log("我被改变了", newValue, oldValue)
}
}
})
// 第二种写法
vm.$watch('name', {
immediate: true,
handler(newValue, oldValue) {
console.log("我被改变了", newValue, oldValue)
}
})
高级用法
const vm = Vue({
el: "#root",
data: {
numbers: {
a: 1,
b: 2
}
},
watch: {
// 单独监听,a的变化
'numbers.a': {
handler() {
console.log("我被更改了")
}
},
// 使用深度监听器
numbers: {
deep: true,
handler() {
console.log("我被更改了")
}
}
}
})
const vm = Vue({
el: "#root",
data: {
name: "hello"
},
watch: {
name() {
// 等一秒钟再执行,这里使用箭头函数是因为,setTimeout是Vue帮我们调用js去运行的,异步的,所以箭头函数在调用的时候,就会自动去找外层的主体,就是name(),而外层的name()就是Vue管理的
setTimeout(()=> {
console.log("Hello 我执行了")
}, 1000)
// 如果是普通函数,那么,普通函数就是浏览器管理的
setTimeout(fucntion(){
console.log("Hello 我执行了")
}, 1000)
}
}
})
<div class="test-class" :class="newClass">单纯绑定</div>
<div class="test-class" :class="objectClass">通过对象绑定,true为开启</div>
<div class="test-class" :class="arrClass">数组绑定,有几个则绑定几个</div>
const vm = Vue({
el: "#root",
data: {
newClass: "helloAClass",
objectClass: {
A: false,
B: true,
C: false
},
arrClass: ["a", "b", "c"]
}
})
<div class="test-class" :style="newStyle">单纯绑定</div>
<div class="test-class" :style="objectStyle">通过对象绑定,true为开启</div>
<div class="test-class" :style="arrStyle">数组绑定,有几个则绑定几个</div>
const vm = Vue({
el: "#root",
data: {
newStyle: "font-size: 10px",
objectStyle: {
fontSize: "20px",
color: "red"
},
objectStyle2: {
fontSize: "20px",
color: "red"
},
arrStyle: [objectStyle, objectStyle2]
}
})
<div v-show="false"> 实际上,只是给style加一个属性:display: none</div>
<div v-if="true">只有条件符合,才会渲染</div>
// template 只能搭配v-if使用,并且不影响结构
<template v-if="true">
<h1>1</h1>
<h1>2</h1>
<h1>3</h1>
</template>
// 遍历数组,testArr=[1,2,3,4]
<div>
<span v-for="(data, index) in testArr" :key="index">
{{data}}
</span>
</div>
// 遍历数组,data=[1,2,3,4],in可以写成of
<div>
<span v-for="(data, index) of testArr" :key="index">
{{data}}
</span>
</div>
// 遍历对象,testObject={name: "123", age: 12, sex="1"}
<div>
<span v-for="(value, key) of testObject" :key="key">
{{key}}:{{value}}
</span>
</div>
// 遍历字符串,testString="hello"
<div>
<span v-for="(str, index) of testString" :key="index">
{{str}}
</span>
</div>
// 遍历指定次数
<div>
<span v-for="(number, index) in 10" :key="index">
{{number}}
</span>
</div>
// 用watch监听
const vm = Vue({
el: "#root",
data: {
search: "",
list: [
{name: "ABCD", age: 18},
{name: "1236", age: 18},
{name: "EDFGBD", age: 18},
{name: "QAZWSXED", age: 18}
],
newList: []
},
watch: {
search: {
// 这里开启immediate,是因为首次会先调用一次watch
immediate: true,
handler(value) {
this.newList = this.list.filter((obj) => {
return obj.name.indexof(value) !== -1
})
}
}
}
// 用computed计算属性
const vm = Vue({
el: "#root",
data: {
search: "",
list: [
{name: "ABCD", age: 18},
{name: "1236", age: 18},
{name: "EDFGBD", age: 18},
{name: "QAZWSXED", age: 18}
]
},
computed: {
// 这里用计算属性,能够实现和watch一样的效果,是因为里面依赖了this.search,search一旦被更新,计算属性就会调用一次
comList() {
return this.list.filter((obj) => {
return obj.name.indexof(this.search) !== -1
})
}
}
})
// 用computed计算属性
const vm = Vue({
el: "#root",
data: {
// 0 原,1 升序,2降序
sortType: 0
search: "",
list: [
{name: "ABCD", age: 18},
{name: "1236", age: 18},
{name: "EDFGBD", age: 18},
{name: "QAZWSXED", age: 18}
]
},
computed: {
// 这里用计算属性,能够实现和watch一样的效果,是因为里面依赖了this.search,search一旦被更新,计算属性就会调用一次
comList() {
const arr = this.list.filter((obj) => {
return obj.name.indexof(this.search) !== -1
})
// 这里进行排序处理
if (this.sortType > 0) {
arr.sort((p1, p2) => {
return this.sortType === 1 ? p1.age - p2.age : p2.age - p1.age
})
}
return arr
}
}
})
data: {
// 数组下标,是没有添加setter和getter的,所以,直接修改数组下标,vue是监视不到变化,页面数据就不会刷新
list: [
// 只有对象里面的属性,才会添加getter和setter
{name: "hello", age: 18}
]
}
// 要想实现让vue监视到数组的变化,要使用指定的7个函数
// 或者使用vue提供的方法,Vue.set(),但是只能对data下面属性的属性进行添加,不能直接添加到data
// 修饰符
<input v-model.trim="text">去除前后空格</input>
<input type="number" v-model.number="text">配合type使用,只能输入数字</input>
<input v-model.lazy="text">失去焦点后,响应</input>
// 单个过滤器
<div>{{name | testFilter}}</div>
// 单个过滤器,并且传值
<div>{{name | test2Filter("hello")}}</div>
// 串联过滤器
<div>{{name | testFilter | newFilter}}</div>
filers: {
testFilter(val) {
return "修改" + val
},
testFilter(val, text) {
return "修改" + val + text
},
newFilter(val) {
return "串联" + val
}
}
// 全局过滤器
Vue.filter("globalFilter", function(val) {
return val
})
<div v-text="name">这里面的div内容无效,会被v-text直接替代</div>
data: {
name: "会直接输出文本内容,相当于格式化
"
}
<div v-html="text">会直接解析内容</div>
data: {
text: "hello
"
}
<div v-cloak>在vue没有加载之前,可以配合css隐藏掉</div>
css样式
[v-cloak] {
display: none;
}
// 只会读取一次值
<div v-once>{{name}}</div>
<div v-pre>直接跳过vue的解析,提高效率</div>
// 1. 初始化会触发自定义指令的刷新
// 2. 所在的模板,被重新解析,自定义指令也会重新刷新
<div v-hello="name">我是特殊内容</div>
data: {
name: "hahaha"
},
directives: {
// 简写
hello(elements, binding) {
elements.innerText = "My name is:" + binding.value
}
// 高级写法
hello: {
bind(elements, binding) {
console.log("初始化调用")
},
inserted(elements, binding) {
console.log("插入元素时,调用")
},
update(elements, binding) {
console.log("更新数据时,调用")
}
},
// 有多个单词这样写
'hello-xixi-haha'(elements, binding) {
elements.innerText = "My name is:" + binding.value
}
}
// 全局指令
Vue.directives("hello", function(elements, binding) {
elements.innerText = "My name is:" + binding.value
})
提示:将会持续优化更新
20221203
Vue模板支持js表达式
一个Vue容器只会接管一个元素
一个元素只能被一个Vue接管
指令语法 v-bind: 和 简写 :
20221202
初识Vue.js
实例化Vue,让Vue运行起来
favicon图标加载问题