vue学习笔记一
VUE自学
一、vue核心的相关学习
本人想先看vue3的但是奈何没文化看不懂,环境也不会装,直接就寄了,只能从头看,笔记时跟着bilibili尚硅谷的视频学习的。
一,搭建vue开发环境
1.下载vue.js
http://v2.cn.vuejs.org/v2/guide/installation.html
2.下载扩展工具
我见过最**的事情了,先是下载很难,最后借的网盘下载完成后,谷歌自己引入后不能用,只能用联想浏览器,真的醉了。
二,hello world案例
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<!-- 一个容器 -->
<div id="root">
<h1>Hello World! 我是{{name}}</h1>
<h1>我的年龄时21</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//创建实例
new Vue({
el:'#root' , // el用于指定当前实例服务于那个容器,值通常为css选择器
data:{//data用于存储数据,数据共el指向对象使用,值暂时先写成一个对象
name:'王鼎舒'
}
})
</script>
</body>
</html>
1.想让vue工作,就必须创建一个vue实例,且要传入一个配置对象
2.root容器里的代码依然符合html规范,只不过混入了一些特殊的vue语法
3.root容器的代码被称为【vue模板】
三,helloworld项目扩展
1.vue容器和实例一一对应
2.真实开发中只有一个vue实例,配合着一些组件一起使用
3.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的属性
4.一旦data中的数据发生改变,那么页面中用到数据的地方也会发生改变。
四,模板语法
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<!--
-->
<div id="root">
<h1>插值语法</h1>
<h3>你好,{{name}}</h3>
<hr>
<h1>语法指令</h1>
<a v-bind:href="url">点击跳转到学习网站1</a>
<a :href="url">点击跳转到学习网站2</a>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue(
{
el:"#root",
data:{
name:"wds",
url:"https://www.huya.com/"
}
}
)
</script>
</body>
</html>
vue模板语法有两大类:
1.插值语法:
功能:用于解析标签体内容
写法:{{xxx}},xxx是js表达式且可以直接读取到data中的属 性
2.指令语法:
功能:用于解析标签(包括:标签属性,标签体内容,绑定事件.....)
举例”v-bind:“简写为“:”且可以直接读取data中的所有属性
备注:vue有很多的指令,且形式都是v-????,此处我们只是用v-bind举个例子。
五,数据绑定
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>数据绑定</title>
</head>
<body>
<div id="root">
单项数据绑定:<input type="text" v-bind:value="name"><br>
双向数据绑定:<input type="text" v-model:value="name"><br>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue(
{
el:'#root',
data:{
name:'我讨厌学习'
}
}
)
</script>
</body>
</html>
vue中有两种数据绑定方式:
1.单向绑定:(v-bind),数据只能从data导向页面
2.双向绑定:(v-model),数据不仅能从data流向页面,还可以从页面流向data
备注;
1.双向绑定一般都应用在表单类元素上(如input select等)
2.v-model:value简写为v-model,其默认收集的就是value
六,el和data的两种写法发
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>Hello World! 我是{{name}}</h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
var a = new Vue({
//第一种写法
// el:'#root' ,
//对象式:data的第一种写法
// data:{
// name:'王鼎舒'
// }
data:function () {
return {
name:'王鼎舒 '
}
}
})
setTimeout(()=>{
//第二种写法
a.$mount('#root')
},1000)
</script>
</body>
</html>
el的两种写法:
1.new Vue的时候配置el的属性
2.先创建Vue的实例,随后再通过vm.¥mount(‘#root’)指定el的值
data的两种写法
1.对象式
2.函数式
选择:目前两种写法都可以,学习组件后,data必须是函数式,否则出错
一个重要的原则:
由Vue管理的函数一定不能写箭头函数
七,理解MVVM模型
v 视图 view 对应data中的数据
m 模型 model 模板
vm 视图模型 vue实例对象
八,数据代理
1.Object.defineProperty
备注:我也不知道学这个是干啥
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<script type="text/javascript">
Vue.config.productionTip = false
let number = 18
let person = {
name:"王鼎舒",
age:"21"
}
Object.defineProperty(person,'sex',{
// value:'man',
// enumberable:true,//控制属性是否可以枚举,默认值是false
// writeable:true,//控制属性是否可以被修改,默认值是false
// configurable:true//控制属性是否可以被删除,默认值是false
//当有人调用person的age属性时,get函数就会被调用,且返回值就是get的值
get:function(){
return 'hello'
}
})
// console.log(Object.keys(person))
console.log(person)
</script>
</body>
</html>xxxxxxxxxx
2.什么是数据代理
通过一个对象代理另一个对象中属性的操作(读/写)
3.vue中的数据代理
九,事件处理
1.事件处理的基本使用
<div id="root">
<h2>{{name}}讨厌学习</h2>
<!-- <button v-on:click="shouInfo">点击产生提示</button> -->
<button @click="shouInfo">点击产生提示</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:"#root",
data:{
name:"王鼎舒"
},
methods:{
shouInfo(event){
//event.target 发生事件的事件目标
// console.log(event.target)
//这里的this指向vm对象
// console.log(this)
alert("绝了")
}
}
})
</script>
2.事件修饰符
vue中的事件修饰符:
1.prevent:默认阻止事件(常用)
2.stop:默认事件冒泡(常用)
3.once:事件只触发一次(常用)
4.capture:使用事件捕获模式
5.self:只有event,target是当前操作的元素时才触发
6.passive:事件只有默认行为执行,无需等待回调执行完毕。
3.键盘事件
1.vue中常用的按键别名:
- 回车 enter
- 删除 delete
- 退出 esc
- 空格 space
- 换行 tab
- 上 up 下 down 左 left 右 right
4.事件总结
修饰符是能连着写的 例如:@click.stop.prevent=“abc”
键盘事件 例如:@keyup.ctrl.y
十,计算属性
1.姓名案例
method方法
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName()}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
firstName:'张',
lastName:'三'
},
methods:{
fullName(){
return this.firstName + '-' + this.lastName
}
}
})
</script>
</body>
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{firstName.slice(0,3)}}-{{lastName }}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
firstName:'张',
lastName:'三'
}
})
</script>
这两种方法效率不高
计算属性方法
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"><br><br>
名:<input type="text" v-model="lastName"><br><br>
姓名:<span>{{fullName}}</span>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el: "#root",
data: {
firstName: '张',
lastName: '三'
},
computed:{
fullName:{
//get当有人读取fullname时,get就会被调用,且返回值就作为fullName的值
//get的调用1.初次调用get时 2.所依赖的属性发生改变
get(){
return this.firstName+'-'+this.lastName
},
set(value){
const arr = value.split("-")
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
}
)
</script>
</body>
</html>
计算属性:
-
定义:要用的属性不存在,要通过已有属性计算
-
原理:底层借助了之前的Object.defineproperty方法提供getter和setter方法
-
优势:与methods方法相比,内部有缓存机制
-
备注:1.计算的属性最终会出现在vm上,可以直接读取
2.如果计算属性要被修改,那就必须要写set函数上去修改
2.计算属性的简写
只考虑读取不考虑修改的时候才能够使用简写形式
3.天气案例 监视属性-watch
<div id="root">
<h2>今天天气很{{nice}}</h2>
<button @click="showInfo">切换天气</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
ishot:true
},
computed:{
nice(){
return this.ishot? "炎热" : "凉爽"
}
},
methods: {
showInfo(){
this.ishot = !this.ishot
}
},
// watch:{
// ishot:{
// immediate:true,//初始化handler时调用一下
// //handler什么时候被调用?当ishot发生改变
// handler(newvalue,oldvalue){
// console.log("天气发生变化",newvalue,oldvalue)
// }
// }
// }
})
vm.$watch('ishot',{immediate:true,
handler(newvalue,oldvalue){
console.log("天气发生变化",newvalue,oldvalue)
}
})
</script>
监视属性watch:
-
当被监视额属性变化时,回调函数自动调用,进行相关操作
-
监视属性必须存在,才能监视
-
监视属性的两种写法
1.new vue时传入watch配置
2.通过vm.$watch监视
4.深度监视
<div id="root">
<h2>今天天气很{{nice}}</h2>
<button @click="showInfo">切换天气</button>
<hr>
<h3>a的值是{{numbers.a}}</h3>
<button @click="numbers.a++">点击让a+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
ishot:true,
numbers:{
a:1,
b:2
}
},
computed:{
nice(){
return this.ishot? "炎热" : "凉爽"
}
},
methods: {
showInfo(){
this.ishot = !this.ishot
}
},
watch:{
//深度监视
numbers:{
deep:true,
handler(){
console.log("a发生改变")
}
},
//监视多级属性中某一属性的变化
'numbers.a':{
handler(){
console.log("a发生改变")
}
}
}
})
</script>
</body>
深度监视:
vue中的watch默认不监视对象内部的值的变化(一层)
配置deep:true可以检测对象 内部值的改变(多层)
备注:
vue自身可以检测对象内部值的改变,但是watch默认不可以
使用watch时根据数据具体结构,决定是否采用深度监视
5.监视属性简写
配置项里之后handler时可以简写
十一,class和style绑定
绑定class样式
1.字符串写法
2.数组写法
3.对象写法
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
<style>
* {
margin: 0px;
padding: 0px;
}
html,
body {
height: 100%;
}
.basic {
width: 200px;
height: 150px;
border: 2px solid black;
}
.normal {
background-color: orange;
}
.happy {
background-color: blue;
}
.sad {
background-color: grey;
}
</style>
</head>
<body>
<div id="root">
<div class="basic" :class="a" @click="changemod">这是一个div</div><br><br>
<div class="basic" :class="classArr" @click="changemod">这是一个div</div><br><br>
<div class="basic" :class="classobj" @click="changemod">这是一个div</div>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
a:"normal",
classArr:['happy','sad','normal'],
classobj:{
happy:false,
sad:false,
normal:true
}
},
methods: {
changemod(){
const arr = ["happy" , "normal" , "sad"]
const index = Math.floor( Math.random()*3)
this.a = arr[index]
}
},
})
</script>
</body>
</html>
style样式绑定一般不使用
十二,条件渲染
v-if:写法
1.v-if=”表达式”
2.v-else=“表达式”
3.v-else-if=“表达式”
适用于切换频率较低的场景,其中不展示dom的元素直接被移出(display:none),三个表达式可以一起使用,但是结构体不能被打断。
v-show:写法
1.v-shou=“表达式”
适用于切换频率较高的场景
不展示的dom不会被移出只是会被隐藏起来。
十三,列表渲染
1,基本列表
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>{{name}}讨厌学习</h1>
<button @click="add">点击添加刘鹏的数据</button>
<ul>
<li v-for="p,index in persons" :key="p.id">{{p.name}}-{{p.age}}<input type="text"></li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
name:"王鼎舒",
persons:[
{id:001,name:"wds",age:18,sex:"man"},
{id:002,name:"lkc",age:81,sex:"man"},
{id:003,name:"lt",age:8,sex:"man"}
]
},
methods: {
add(){
const p = {id:'004',name:"lp",age:'100+',sex:'woman'}
this.persons.unshift(p)
}
},
})
</script>
</body>
</html>
面试题:react、vue中的key有什么作用?(key的内部原理)
虚拟DOM中key的作用:key是虚拟DOM中对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下:
对比规则:
旧虚拟DOM中找到了与新虚拟DOM相同的key:
若虚拟DOM中内容没变, 直接使用之前的真实DOM
若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM
旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到到页面
用index作为key可能会引发的问题:
若对数据进行逆序添加、逆序删除等破坏顺序操作:会产生没有必要的真实DOM更新 ==> 界面效果没问题, 但效率低
若结构中还包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
开发中如何选择key?
最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值
如果不存在对数据的逆序添加、逆序删除等破坏顺序的操作,仅用于渲染列表,使用index作为key是没有问题的
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
2.列表过滤
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>人员列表</h1>
<hr>
<input type="text" placeholder="请输入姓名" v-model="keyword">
<li v-for="(p,index) in filpersons" :key="p.id">{{p.name}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: "#root",
data: {
name: "王鼎舒",
keyword: '',
persons: [
{ id: 001, name: "wds", age: 18, sex: "男" },
{ id: 002, name: "lkc", age: 81, sex: "男" },
{ id: 003, name: "lt", age: 8, sex: "男" },
{ id: 004, name: "nm", age: 18, sex: "男" },
{ id: 005, name: "dly", age: 81, sex: "男" },
{ id: 006, name: "adsaddasd", age: 8, sex: "男" }
],
filpersons: []
},
watch: {
keyword: {
immediate: true,
handler(value){
this.filpersons = this.persons.filter((p) => {
return p.name.indexOf(value) !== -1
})
}
}
}
})
</script>
</body>
</html>
3.列表排序
出了问题
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>人员列表</h1>
<hr>
<input type="text" placeholder="请输入姓名" v-model="keyword">
<button @click="sortType=2">升序排序</button>
<button @click="sortType=1">降序排序</button>
<button @click="sortType=0">原顺序</button>
<li v-for="(p,index) in filpersons" :key="p.id">{{p.name}}-{{p.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: "#root",
data: {
name: "王鼎舒",
keyword: '',
sortType: 0 ,
persons: [
{ id: 001, name: "wds", age: 18, sex: "男" },
{ id: 002, name: "lkc", age: 81, sex: "男" },
{ id: 003, name: "lt", age: 8, sex: "男" },
{ id: 004, name: "nm", age: 28, sex: "男" },
{ id: 005, name: "dly", age: 831, sex: "男" },
{ id: 006, name: "adsaddasd", age: 44, sex: "男" }
],
},
computed:{
filpersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyword) !== -1
})
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age
})
}
return arr
}
}
})
</script>
</body>
</html>
4.数据更新时的问题
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>{{name}}讨厌学习</h1>
<button @click="ubdatewds">修改wds的数据的数据</button>
<ul>
<li v-for="p,index in persons" :key="p.id">{{p.name}}-{{p.age}}<input type="text"></li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
name:"王鼎舒",
persons:[
{id:001,name:"wds",age:18,sex:"man"},
{id:002,name:"lkc",age:81,sex:"man"},
{id:003,name:"lt",age:8,sex:"man"}
]
},
methods: {
ubdatewds(){
// //点击按钮时数据直接发生了更新
// this.persons[0].age = 21
//点击后数据发生更新但是页面不显示
this.persons[0] = {id:001,name:"wds", age:21, sex:"man"}
}
},
})
</script>
</body>
</html>
5.vue数据检测的原理
通过data数据,利用vm代理data中的数据
Vue监视数据的原理:
vue会监视data中所有层次的数据
如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据
对象中后追加的属性,Vue默认不做响应式处理
如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value)
vm.$set(target,propertyName/index,value)
如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
调用原生对应的方法对数组进行更新
重新解析模板,进而更新页面
在Vue修改数组中的某个元素一定要用如下方法:
使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象(data等) 添加属性
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
6.set()方法
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>{{wdsinfo.name}}的爱好列表</h1>
<h2>年龄:{{wdsinfo.age}}</h2>
<button @click="addage">添加年龄</button>
<ul>
<li v-for="(h,index) in hobby" :key="index">{{h}}</li>
</ul>
<ul>
<li v-for="(f,index) in wdsinfo.friends" :key="index">{{f.name}}--{{f.age}}</li>
</ul>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm =new Vue({
el:"#root",
data:{
wdsinfo:{
name:"王鼎舒",
school:"山西农业大学",
friends:[
{name:"qqq",age:"22"},
{name:"www",age:"24"},
{name:"eee",age:"25"}
]
},
hobby:["抽烟","喝酒","烫头"]
},
methods: {
addage(){
this.$set(this.wdsinfo,"age",21)
}
},
})
</script>
</body>
</html>
7.总结
十四,表单渲染
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<form @submit.prevent="demo">
账号:<input type="text" v-model="account"><br><br>
密码:<input type="password" v-model="password"><br><br>
性别:
男<input type="radio" name="sex" v-model="sex" value="male">
女<input type="radio" name="sex" v-model="sex" value="female"><br><br>
爱好:
<input type="checkbox" v-model="hobby" value="sing">唱
<input type="checkbox" v-model="hobby" value="jump">跳
<input type="checkbox" v-model="hobby" value="rap">rap
<input type="checkbox" v-model="hobby" value="bassketball">篮球<br><br>
所属校区
<select v-model="city">
<option value="taiyuan">太原</option>
<option value="taigu">太谷</option>
<option value="yuncheng">运城</option>
<option value="changzhgi">长治</option>
<option value="datong">大同</option>
</select>
<br><br>
其他信息:
<textarea cols="30" rows="10">
</textarea><br><br>
<input type="checkbox">
阅读并接受<a href="#">《用户协议》</a>
<br><br>
<button>提交 </button>
</form>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:"#root",
data:{
account:'',
password:'',
sex:'male',
// 多组勾选框要写成数组形式,否则默认识别check的值
hobby:[],
city:'太原'
},
methods: {
demo(){
console.log(this._data)
}
},
})
</script>
</body>
</html>
总结:
收集表单数据:
若:,则v-model收集的是value值,用户输入的内容就是value值
若:,则v-model收集的是value值,且要给标签配置value属性
若:
没有配置value属性,那么收集的是checked属性(勾选 or 未勾选,是布尔值)
配置了value属性:
v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
v-model的初始值是数组,那么收集的就是value组成的数组
v-model的三个修饰符:
lazy:失去焦点后再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
十五,内置指令
1.v-text
总结,没啥用
2.v-html
1.向指定节点中渲染包含html结构的内容
2.与插值语法的区别:
1.v-html公共替换掉节点的内容{{xxx}}则不会
2.v-html可以识别html结构
3.严重注意:v-html有安全性问题
1.一定要在可信的网站上使用v-html,绝对不要用在提交内容上。
3.v-cloak
指令是没有值的
本质是一个特殊的属性,vue实例创建完毕并且接管容器后,会删掉v-cloak属性
使用css配合c-cloak可以解决网速缓慢时,页面内展示出{{xxx}}的问题
4.v-once
1.v-once所在的节点在初次动态渲染之后,就视为静态内容了
2.以后数据更新的改变不会引起v-once所在结构的更新,可以用于性能的优化。
5.v-pre
1.跳过其所在节点的编译过程
2.可利用它跳过,没有使用指令语法,没有使用插值语法的节点,会加快编译。
十六,自定义属性
说白了就是封装dom
有两种方式
1.函数式
2.对象式
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h2>当前值是:<span v-text="n"></span></h2>
<h2>扩大10倍后的值<span v-big="n"></span></h2>
<button @click="n++">n+1</button>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
n :1
},
//函数式
directives:{
//big函数什么时候会被调用1.指令与元素成功绑定时2.指令所在的模板被重新解析时
big(element,binding){
element.innerText = binding.value *10
},
find:{
//指令与元素绑定时
bind(){
},
//元素被插入到页面时
inserted(){
},
//指令所在的模板被调用时
update(){
}
}
}
})
</script>
</body>
</html>
十七,生命周期
二,vue组件的理解,开始组件化编程
组件就是一块砖,哪里需要哪里搬
一,对组件的理解
定义:用来实现局部(特定)功能效果的代码集合(html/css/js/image/....)
作用:复用代码,简化项目编码,提高运行效率。
传统方式编写应用存在的问题:
1.依赖关系混乱,不好维护。
2.代码复用率不高。
使用组件的方式编写代码。
二,非单文件组件
一,基本构成
上了一波大当,这玩意几乎不用,还让我听了30分钟。
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<h1>{{title}}</h1><br>
<school></school>
<hr>
<student></student>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//创建school组件
const school = Vue.extend({
//组件定义时,不要写el属性
template: `<div>
<h2>学校姓名:{{schoolname}}</h2>
<h2>学校地址:{{address}}</h2>
</div>`,
data() {
return {
schoolname: "山西农业大学",
address: "山西晋中太谷县"
}
}
})
//创建学生组件
const student = Vue.extend({
//组件定义时,不要写el属性
template: `<div>
<h2>学生姓名:{{studentname}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>`,
data() {
return {
studentname: "王鼎舒",
age: 22
}
}
})
//创建vm
new Vue({
el: "#root",
data:{
title:"你好啊"
},
components: {
school: school,
student: student
}
})
// new Vue({
// el:'#root',
// data:{
// schoolname:"山西农业大学",
// address:"山西晋中太谷县",
// studentname:"王鼎舒",
// age:22,
// }
// })
</script>
</body>
</html>
二,注意事项
关于组件名:
一个单词组成:
第一种写法(首字母小写):school
第二种写法(首字母大写):School
多个单词组成:
第一种写法(kebab-case命名):my-school
第二种写法(CamelCase命名):MySchool (需要Vue脚手架支持)
备注:
组件名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行
可以使用name配置项指定组件在开发者工具中呈现的名字
关于组件标签:
第一种写法:
第二种写法:
备注:不使用脚手架时,
一个简写方式:const school = Vue.extend(options)可简写为:const school = options
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
三,组件的嵌套
<!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">
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<title>Document</title>
</head>
<body>
<div id="root">
<school></school>
<hr>
</div>
<script type="text/javascript">
Vue.config.productionTip = false
//定义学生组件
const student = Vue.extend({
template:`<div>
<h2>学生名称:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>`,
data(){
return{
name:"王鼎舒",
age:18
}
}
})
//定义school组件
const school = Vue.extend({
template:`<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>`,
data(){
return{
name:"山西农业大学",
address:"太谷",
}
},
components:{
student
}
})
new Vue({
el:"#root",
components:{
school:school,
student:student
}
})
</script>
</body>
</html>
四,VueComponent
关于VueComponent:
school组件本质是一个名为VueComponent的构造函数,且不是程序员定义的,是Vue.extend生成的
我们只需要写
特别注意:每次调用Vue.extend,返回的都是一个全新的VueComponent!
关于this指向:
组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是VueComponent实例对象
new Vue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数 它们的this均是Vue实例对象
VueComponent的实例对象,以后简称vc(也可称之为:组件实例对象)
Vue的实例对象,以后简称vm
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
五,组件和实例的内置关系
(我听到头疼,是真的头疼,学前端的我恶补了一下后端的基础,绝了)
Vueconpontent.prototype.proto === vue.proto
个人浅薄理解:一个构造函数,有两个对象,一个是实例对象,就是定义构造函数时,函数内写的对象,另一个是原型对象,原型对象是系统给的,不是我们写的,本来组件的原型对象的原型对象因该是object对象,但是vue让组件的原型对象的原型对象指向vue的原型对象,于是组件就能够使用vue原型对象的方法和属性。
(说实话没听懂)
三,单文件组件
内容有好多,
首先我们应该创建vue文件来创建我们的组件,为了让其他组件能够服用必须模块化语言暴露组件
school.vue
<template>
<!-- 组件的结构 -->
<div>
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>
<script>
// 组件交互的相关代码
export default {
name:'School',
data() {
return {
name: "山西农业大学",
address: "太谷",
}
},
}
</script>
<style>
/* 组件的样式 */
.demo {
background-color: orange;
}
</style>
<!-- const school = Vue.extend({
template:`<div>
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<student></student>
</div>`,
data(){
return{
name:"山西农业大学",
address:"太谷",
}
},
components:{
student
}
}) -->
student.vue
<template>
<div class="demo2">
<h2>学生名称:{{ name }}</h2>
<h2>学生年龄:{{ age }}</h2>
</div>
</template>
<script>
export default {
name:"student",
data(){
return{
name:"王鼎舒",
agae:"21"
}
},
}
</script>
<style>
.demo {
background-color: blue;
}
</style>
这里要注意定义组件的名称的时候使用两个单词双驼峰形式写,否则在放入脚手架后会报错
随后就要创建vue的老大哥App.vue 把之前的模块组合起来
App.vue
<template>
<div>
<SchoolInfo></SchoolInfo>
<StudentInfo></StudentInfo>
</div>
</template>
<script>
import SchoolInfo from './components/school.vue'
import StudentInfo from './components/student.vue'
export default {
name:'App',
template:'<app></app>',
components:{
SchoolInfo,
StudentInfo
}
}
</script>
这串代码是我放入脚手架之后的代码所以组建的名称都发生了改变,改变就是在原基础名称后面写上Info
之后编写main.js代码,引入vue对象和App.vue方便我们操作
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
最后创建index.html文件来创建一个容器放入我们之前的代码
这里引入代码时将引入的代码放在body最下面,放置出现创建但是没有渲染的问题
<!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>Document</title>
</head>
<body>
<div id="root">
<App></App>
</div>
<script type="text/javascript" src="../vue.baise/vue.js"></script>
<script type="text/javascript" src="./main.js"></script>
</body>
</html>
大概我们要写的就是这么多
但是我们写好的内容是跑不起来的需要脚手架的帮助才能跑起来。
三,vue脚手架的相关知识
终于是学到vue脚手架了折磨,痛苦啊。
一,创建脚手架
如果下载缓慢请配置 npm 淘宝镜像:npm config set registry http://registry.npm.taobao.org
全局安装@vue/cli:npm install -g @vue/cli
切换到你要创建项目的目录,然后使用命令创建项目:vue create xxxx
选择使用vue的版本
启动项目:npm run serve
暂停项目:Ctrl+C
Vue 脚手架隐藏了所有 web
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
二,分析脚手架结构
.文件目录
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ └── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
└── package-lock.json: 包版本控制文件
————————————————
版权声明:本文为CSDN博主「梦入_凡尘」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_55593227/article/details/119717498
最后将代码放入脚手架中
非常的离谱,头一次执行代码没出什么太大的错误,
这里吐槽之前学习的maven和ssm框架简直是噩梦。
三,render函数
vue.js与vue.runtime.xxx.js的区别:
1.vue.js是完整版的Vue,包含核心功能加模板解析
2.vue.runtime.xxx.js是运行版的Vue,只包含核心功能,没有模板解析器,需要render函数接收creatElement函数去指定具体内容。
四,修改默认配置
没仔细听,默认的配置我们最好还是不要手欠改一下。
五,ref属性
1.id属性的替代者
2.应用在html标签上,获取的是真实的dom元素,应用在组件标签上的的是组建的实例对象。
3.使用方式,在html上获取的是真实的dom元素,应用在组件标签上的是组件实例对象。
<template>
<!-- 模板文档只能有一个容器 -->
<div>
<h1 ref="text">真TMD服了!!!</h1>
<MyName></MyName>
<button @click="showMe">点我输出test的节点</button>
</div>
</template>
<script>
import MyName from "./components/MyName.vue";
export default {
name: "App",
components: {
MyName,
},
methods: {
showMe(){
console.log(this.$refs.text)
}
},
};
</script>
六,props配置
七,mixin混合
遇到组件script部分有重复的地方的时候写这个
八,ToDoList案例
1.组件化编码流程(通用)
1.实现静态组件:抽取组件,使用组件实现静态页面的效果
2.展示动态数据
2.1数据的类型、名称是什么。
2.2数据保存在那个组件。
3.交互-从绑定事件开始
2.代码部分
header.vue
<template>
<div class="todo-header">
<input type="text" placeholder="请输入你的任务名称,按回车键确认" @keyup.enter="add"/>
</div>
</template>
<script>
import {nanoid} from 'nanoid'
export default {
name: "MyHeader",
methods:{
add(e){
if(!e.target.value) return alert("不能输入空值")
const todoobj = {id:nanoid(),title:e.target.value,completed:false}
//将用户的输入包装成为一个对象
this.receive(todoobj)
e.target.value=''
}
},
props:["receive","todos"]
};
</script>
<style scoped>
.todo-header input {
width: 560px;
height: 28px;
font-size: 14px;
border: 1px solid #ccc;
border-radius: 4px;
padding: 4px 7px;
}
.todo-header input:focus {
outline: none;
border-color: rgba(82, 168, 236, 0.8);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}
</style>
footer.vue
<template>
<div class="todo-footer">
<label>
<input type="checkbox" :checked="isAll" @change="checkAll"/>
</label>
<span>
<span>已完成{{todoDone}}</span> / 全部{{todos.length}}
</span>
<button class="btn btn-danger" @click="deleteAll">清除已完成任务</button>
</div>
</template>
<script>
export default {
name: "MyFooter",
computed: {
total(){
return this.todos.length
},
todoDone() {
return this.todos.reduce((pre,todo)=> pre + (todo.completed ? 1 : 0),0)
},
isAll(){
return this.todoDone === this.total && this.todoDone >0
}
},
methods:{
checkAll(e){
this.checkAllTodo(e.target.checked)
},
deleteAll(){
this.clearAlltodo()
}
},
props: ["todos","checkAllTodo","clearAlltodo"],
};
</script>
<style scoped>
/*footer*/
.todo-footer {
height: 40px;
line-height: 40px;
padding-left: 6px;
margin-top: 5px;
}
.todo-footer label {
display: inline-block;
margin-right: 20px;
cursor: pointer;
}
.todo-footer label input {
position: relative;
top: -1px;
vertical-align: middle;
margin-right: 5px;
}
.todo-footer button {
float: right;
margin-top: 5px;
}
</style>
list.vue
<template>
<ul class="todo-main">
<MyItem
v-for="todoobj in todos"
:key="todoobj.id"
:todo="todoobj"
:checkTodo="checkTodo"
:deletetodo="deletetodo"></MyItem>
</ul>
</template>
<script>
import MyItem from "./MyItem.vue";
export default {
name: "MyList",
components: {
MyItem,
},
props:["todos","checkTodo","deletetodo"],
methods:{
}
};
</script>
<style scoped>
/*main*/
.todo-main {
margin-left: 0px;
border: 1px solid #ddd;
border-radius: 2px;
padding: 0px;
}
.todo-empty {
height: 40px;
line-height: 40px;
border: 1px solid #ddd;
border-radius: 2px;
padding-left: 5px;
margin-top: 10px;
}
</style>
item.vue
<template>
<li>
<label>
<input type="checkbox" :checked="todo.completed" @change="handleCheck(todo.id)"/>
<span>{{todo.title}}</span>
</label>
<button class="btn btn-danger" @click="removetodo(todo.id)">删除</button>
</li>
</template>
<script>
export default {
name: "MyItem",
props:["todo","checkTodo","deletetodo"],
methods:{
handleCheck(id){
this.checkTodo(id)
},
removetodo(id){
if(confirm("你确定吗?")){
this.deletetodo(id)
}
}
}
};
</script>
<style scoped>
/*item*/
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover{
background-color: #ddd;
}
li:hover button{
display: block;
}
</style>
app.vue
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<MyHeader :receive="receive"></MyHeader>
<MyList :todos="todolist" :checkTodo="checkTodo" :deletetodo="deletetodo"></MyList>
<MyFooter :clearAlltodo="clearAlltodo" :todos="todolist" :checkAllTodo="checkAllTodo"></MyFooter>
</div>
</div>
</div>
</template>
<script>
import MyHeader from "./components/MyHeader.vue";
import MyFooter from "./components/MyFooter.vue";
import MyList from "./components/MyList.vue";
export default {
name: "App",
components: {
MyHeader,
MyFooter,
MyList,
},
data(){
return{
todolist:[
{id:'001',title:'唱',completed:true},
{id:'002',title:'跳',completed:false},
{id:'003',title:'rap',completed:true},
{id:'004',title:'篮球',completed:true}
]
}
},
methods:{
receive(x){
this.todolist.unshift(x)
},
checkTodo(id){
this.todolist.forEach((todo) => {
if(todo.id === id) todo.completed = !todo.completed
});
},
deletetodo(id){
this.todolist = this.todolist.filter((todo) =>{
return todo.id !== id
});
},
checkAllTodo(completed){
this.todolist.forEach((todo)=>{
todo.completed = completed
})
},
clearAlltodo(){
this.todolist = this.todolist.filter((todo)=>{
return !todo.completed
})
}
}
};
</script>
<style>s
body {
background: #fff;
}
.btn {
display: inline-block;
padding: 4px 12px;
margin-bottom: 0;
font-size: 14px;
line-height: 20px;
text-align: center;
vertical-align: middle;
cursor: pointer;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
0 1px 2px rgba(0, 0, 0, 0.05);
border-radius: 4px;
}
.btn-danger {
color: #fff;
background-color: #da4f49;
border: 1px solid #bd362f;
}
.btn-danger:hover {
color: #fff;
background-color: #bd362f;
}
.btn:focus {
outline: none;
}
.todo-container {
width: 600px;
margin: 0 auto;
}
.todo-container .todo-wrap {
padding: 10px;
border: 1px solid #ddd;
border-radius: 5px;
}
</style>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现