目录
v-for遍历对象/数组/字符串
key的作用相当于人的身份证号
<div id="root">
<!-- 遍历列表 -->
<ul>
<!-- <li v-for="person in persons" :key="person.id">{{person.name}}-{{person.age}}</li> -->
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}---{{p.age}}
</li>
</ul>car
<!-- 遍历对象 -->
<ul>
<!-- <li v-for="(a,b) in car" >
{{a}}---{{b}} -->
<li v-for="(value,k) in car" :key="k">
{{k}}---{{value}}
</li>
</ul>
<!-- 遍历字符串 -->
<ul>
<!-- <li v-for="(a,b) in str">i
{{a}}---{{b}} -->
<li v-for="(char,i) in str" :key="i">
{{char}}---{{i}}
</li>
</ul>
</div>
<script>
const v = new Vue({
el: '#root',
data: {
persons: [
{ id: '001', name: '张三', age: 18 },
{ id: '002', name: '李四', age: 19 },
{ id: '003', name: '王五', age: 15 }
],
car: {
name: '奥迪A8',
price: '80万',
color: '黑色'
},
str: 'hello'
}
})
</script>
基本列表过滤
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="./vue.js"></script>
<body>
<div id="root">
<!-- 遍历列表 -->
<input type="text" placeholder="请输入名字" v-model="keyword">
<ul>
<!-- <li v-for="person in persons" :key="person.id">{{person.name}}-{{person.age}}</li> -->
<li v-for="(p,index) in filPersons" :key="p.id" >
{{p.name}}---{{p.age}}---{{p.sex}}
</li>
</ul>
</div>
<script>
//1.使用watch实现过滤效果
// const v = new Vue({
// el: '#root',
// data: {
// keyword:'',
// persons: [
// { id: '001', name: '周冬雨', age: 18,sex:'女' },
// { id: '002', name: '周杰伦', age: 19,sex:'男' },
// { id: '003', name: '李红梅', age: 15,sex:'女' },
// { id: '004', name: '周妹梅', age: 15,sex:'女' },
// { id: '005', name: '马冬梅', age: 25,sex:'女' },
// ],
// filPersons:[]
// },
// watch:{
// keyword:{
// immediate:true, //立即执行
// handler(val){
// this.filPersons = this.persons.filter((p)=>{
// return p.name.indexOf(val) !==-1 //使用indexOf时若没有检测出数组里面有关键字则返回-1
// })
// }
// }
// }
// })
//2.使用computed实现过滤效果
new Vue({
el:'#root',
data: {
keyword:'',
persons: [
{ id: '001', name: '周冬雨', age: 18,sex:'女' },
{ id: '002', name: '周杰伦', age: 19,sex:'男' },
{ id: '003', name: '李红梅', age: 15,sex:'女' },
{ id: '004', name: '周妹梅', age: 15,sex:'女' },
{ id: '005', name: '马冬梅', age: 25,sex:'女' },
]
},
computed: {
filPersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyword) !== -1
})
}
}
})
</script>
</body>
</html>
列表排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="./vue.js"></script>
<body>
<div id="root">
<!-- 遍历列表 -->
<input type="text" placeholder="请输入名字" v-model="keyword">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<!-- <li v-for="person in persons" :key="person.id">{{person.name}}-{{person.age}}</li> -->
<li v-for="(p,index) in filPersons" :key="p.id" >
{{p.name}}---{{p.age}}---{{p.sex}}
</li>
</ul>
</div>
<script>
new Vue({
el:'#root',
data: {
sortType:0, //0代表原顺序 1降序 2升序
keyword:'',
persons: [
{ id: '001', name: '周冬雨', age: 18,sex:'女' },
{ id: '002', name: '周杰伦', age: 19,sex:'男' },
{ id: '003', name: '李红梅', age: 15,sex:'女' },
{ id: '004', name: '周妹梅', age: 15,sex:'女' },
{ id: '005', name: '马冬梅', age: 25,sex:'女' },
]
},
computed: {
filPersons(){
const arr = 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
}
}
})
//简单案例示范(对上面代码的解释)
// let arr = [1,3,2,6,5,4]
// arr.sort((a,b)=>{
// return a-b //升序 |b-a 降序
// })
// console.log(arr);
</script>
</body>
</html>
-
之前data数据里面没有对象sex,需要依据情况添加(两种方式),不允许在vm或vm的根数据对象上添加没有存在的对象属性。
1.Vue.set(target,属性名,属性值) 如:Vue.set(vm.student,'sex','男')
2.Vue.$set(target,属性名,属性值) 如:Vue.$set(vm.student,'sex','男')
-
往数组里面添加数组值,需使用数组的相关方法如:push、pop等vue才能检测得到
收集表单数据
v-model三个修饰符
- lazy : 失去焦点再收集数据
- number :输入字符串转为有效的数字
- trim :输入首尾空格过滤
过滤器
仅使用于简单逻辑的处理,一般用于插值语法和v-bind属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="./vue.js"></script>
<script src="./dayjs.min.js"></script> <!-- 使用的bootcdn里面JavaScript 库 -->
<body>
<div id="root">
<!-- 计算属性实现 -->
<h3>现在是:{{fmtTime}}</h3>
<!-- methods实现 -->
<h3>现在是:{{getfmtTime()}}</h3>
<!-- 过滤器实现 -->
<h3>现在是:{{Time | Timeformater}}</h3>
<h3>现在是:{{Time | Timeformater('YYYY_MM_DD')}}</h3>
</div>
<script>
// 全局过滤器,当有两个vm实例时采用
Vue.filter('Timeformater',function (value,str='YYYY年MM月DD日 HH:mm:ss') {
return dayjs(value).format(str)
})
new Vue({
el: '#root',
data: {
Time:1691052368976
},
computed: {
fmtTime(){
return dayjs(this.Time).format('YYYY年MM月DD日 HH:mm:ss')
}
},
methods: {
getfmtTime(){
return dayjs(this.Time).format('YYYY年MM月DD日 HH:mm:ss')
}
},
// 局部过滤器
// filters:{
// Timeformater(value,str='YYYY年MM月DD日 HH:mm:ss'){
// return dayjs(value).format(str)
// }
// }
})
</script>
</body>
</html>
部分vue内置指令
v-model
说明: 在表单输入元素或组件上创建双向绑定。仅限: <input>、<select>、 <textarea>、components
修饰符:
.lazy ——监听 change 事件而不是 input
.number ——将输入的合法符串转为数字
.trim ——移除输入内容两端空格v-pre
说明: 跳过该元素及其所有子元素的编译。详细描述:
元素内具有 v-pre,所有 Vue 模板语法都会被保留并按原样渲染。最常见的用例就是显示原始双大括号标签及内容。<span v-pre>{{ this will not be compiled }}</span>
v-once
说明: 仅渲染元素和组件一次,并跳过之后的更新。详细描述: 在随后的重新渲染,元素/组件及其所有子项将被当作静态内容并跳过渲染。这可以用来优化更新时的性能。
<!-- 单个元素 -->
<span v-once>This will never change: {{msg}}</span>
<!-- 带有子元素的元素 -->
<div v-once>
<h1>comment</h1>
<p>{{msg}}</p>
</div>
<!-- 组件 -->
<MyComponent v-once :comment="msg" />
<!-- `v-for` 指令 -->
<ul>
<li v-for="i in list" v-once>{{i}}</li>
</ul>v-cloak
说明: 用于隐藏尚未完成编译的 DOM 模板。详细描述:
该指令只在没有构建步骤的环境下需要使用。当使用直接在 DOM 中书写的模板时,可能会出现一种叫做“未编译模板闪现”的情况:用户可能先看到的是还没编译完成的双大括号标签,直到挂载的组件将它们替换为实际渲染的内容。
v-cloak 会保留在所绑定的元素上,直到相关组件实例被挂载后才移除。配合像 [v-cloak] { display: none } 这样的 CSS 规则,它可以在组件编译完毕前隐藏原始模板。
[v-cloak] {
display: none;
}
1
2
3
<div v-cloak>
{{ message }}
</div>
自定义vue指令
全局注册注册:主要是用过Vue.directive方法进行注册
Vue.directive第一个参数是指令的名字(不需要写上v-前缀),第二个参数可以是对象数据,也可以是一个指令函数
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
}
})
局部注册通过在组件options选项中设置directive属性
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus() // 页面加载完成之后自动让输入框获取到焦点的小功能
}
}
}
然后你可以在模板中任何元素上使用新的 v-focus property,如下:
<input v-focus />
生命周期
引出生命周期案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<script src="./vue.js"></script>
<body>
<div id="root">
<h1 :style="{opacity}">hello vue生命周期</h1>
</div>
<script>
const vm = new Vue({
el: '#root',
data: {
opacity: 1
},
mounted() {
setInterval(()=>{
this.opacity -= 0.01
if (this.opacity <=0)
this.opacity = 1
},16)
},
})
// 通过外部的定时器实现,不推荐
</script>
</body>
</html>
生命周期详细图解
生命周期总结:
组件化编程
- 非单文件组件:一个文件中包含n个组件
- 单文件组件:一个文件中只包含1个组件
局部注册:靠 new Vue的时候传入components选项
全局注册:靠Vue.component('组件名',组件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
</head>
<body>
<div id="root">
<h2>{{name}}</h2>
<idea></idea>
</div>
<script>
<!-- 1.创建组件 -->
const s=Vue.extend({
template:`
<div>
<h1>{{gooidea}}</h1>
</div>
`,
data () {
return {
gooidea:'好主意呀!'
}
}
})
// 全局注册
Vue.component('idea',s)
new Vue({
el:'#root',
data:{
name:'hello'
},
// 2.注册组件(局部注册)
// components:{
// idea:s
// }
})
</script>
</body>
</html>
props的三种编写方式
组件界面
<template>
<div>
<h1>{{text}}</h1>
<label for="">学生姓名:</label><span>{{name}}</span><br>
<label for="">学生年龄:</label><span>{{age}}</span><br>
<label for="">学生性别:</label><span>{{sex}}</span>
</div>
</template>
<script>
export default {
data () {
return {
text:'学生界面'
}
},
//1.简单接收
// props:['name','sex','age']
//2.接收的同时对数据进行限制
// props:{
// name:String,
// age:Number,
// sex:String
// }
//3.接收的同时对数据进行限制,对必要性限制及默认值的配置
props:{
name:{
type:String,
require:true //name是必须的
},
age:{
type:Number,
default:99
},
sex:{
type:String,
require:true
}
}
}
</script>
主界面
<template>
<div id="app">
<StudentPage name="李四" sex="女" :age="18"/>
</div>
</template>
<script>
import StudentPage from './components/StudentPage.vue'
export default {
name: 'App',
components: {
StudentPage
}
}
</script>
mixin:使用场景-多个组件共有的属性使用
创建一个mixin.js文件
export const showalert ={
methods: {
showadress(){
alert(this.adress)
}
},
}
分别在两个组件界面引用showadress方法
注意:一定需要添加mixins:[showalert],也就是在mixin.js里面暴露出的变量,不然会显示方法没有引用上。
<template>
<div>
<h3>地址:{{adress}}</h3>
<button @click="showadress">点击弹窗</button>
</div>
</template>
<script>
import { showalert } from '@/mixin';
export default {
name:'SchoolPage',
data () {
return {
adress:'长沙市望城区黄金园街道',
}
},
mixins:[showalert]
}
</script>
<template>
<div>
<h1>{{text}}</h1>
<label for="">学生姓名:</label><span>{{name}}</span><br>
<label for="">家庭住址:</label><span>{{adress}}</span>
<button @click="showadress">点击弹窗</button>
</div>
</template>
<script>
import { showalert } from '@/mixin';
export default {
name:'StudentPage',
data () {
return {
text:'学生界面',
name:'张三',
adress:'长沙市望城区黄金园街道'
}
},
mixins:[showalert]
}
</script>
vue scoped样式
解决组件样式冲突问题 在style标签中加入scoped属性,实现局部生效
组件化编码流程
- 实现静态组件:抽取组件,使用组件实现静态页面效果
- 展示动态数据:
2.1数据的类型,名称是什么?
2.2数据保存在哪个组件?
- 交互-------从绑定事件监听开始
Todo-list案例
源码在此文章中,需要自取:npm run dev