vue的官方文档
创建一个vue的实例
const x = new vue({});
下面的代码快速了解vue,快速知道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>Documenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="app">
<h1>hello,{{message}}h1>
双括号里可以写javascript的表达式 如a,a+b,demo(a),x===y?'a':'b'等
不是代码:如if(){} for(){}
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
// 创建一个实例
new Vue({
el:'#app', //el 用于指定当前Vue位于哪个容器中,值通常为为css选择器==字符串==
data:{ //data中用于存放数据,数据供el所指定的容器去使用,值占时先写成一个对象。
message:'你好',
}
})
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>Documenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
单向数据的绑定: <input type="text" v-bind:value="name"><br>
双向数据的绑定: <input type="text" v-model:value="name"><br>
单向数据的绑定: <input type="text" :value="name"><br>
双向数据的绑定: <input type="text" v-model="name"><br>
<h1 v-mode:x="name">你好啊h1>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
new Vue({
el:"#root",
data:{
name:"为将去哪"
}
})
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>Documenttitle>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>你好,{{name}}h1>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
// el的两种写法
/* const v = new Vue({
// el:"#root", 第一种写法
data:{
name:"鲸落"
}
})
console.log(v);
setTimeout(()=>{
v.$mount('#root') //第二种写法对于有定时器的时候更加的好
},1000) */
//data的两种写法
const x = new Vue({
// 第一种在上面
// data的函数式写法(第二种写法)
el:"#root",
data:()=>{
console.log("此处的this",this);
return{
name:'鲸落'
}
}
})
script>
body>
html>
Object.defineProperty
方法这个方法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>Documenttitle>
head>
<body>
<script>
let person = {
name:"金落",
sex:'男',
age:12
}
console.log(person);
script>
body>
html>
let person = {
name:"金落",
sex:'男',
// age:12
}
Object.defineProperty(person,'age',{
value:12
})
console.log(person);
这个时候的通过这个方法添加的属性age
是不参加遍历的(也就是不参加枚举)
let person = {
name:"金落",
sex:'男',
// age:12
}
Object.defineProperty(person,'age',{
value:12
})
/* Object.keys()这个方法可以把传入其中的
对象的属性名提取出来组成一个数组 */
console.log(Object.keys(person));
进一步分析
let person = {
name:"金落",
sex:'男',
}
Object.defineProperty(person,'age',{
value:12,
enumerable:true //控制属性是否可以枚举
})
/* Object.keys()这个方法可以把参入其中的
对象的属性名提取出来组成一个数组 */
console.log(Object.keys(person));
let number = 22;
let person = {
name:"金落",
sex:'男',
}
Object.defineProperty(person,'age',{
/* 当有人读取person的age属性时,
get函数(getter)就会被调用,且返回值就是age的值 */
get:function(){
return number
}
})
/* Object.keys()这个方法可以把参入其中的
对象的属性名提取出来组成一个数组 */
console.log(person);
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>回顾Object.defineproperty方法title>
head>
<body>
<script type="text/javascript" >
let number = 18
let person = {
name:'张三',
sex:'男',
}
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
// get:function()可以简写成get()
get(){
console.log('有人读取age属性了')
return number
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
})
// console.log(Object.keys(person))
console.log(person)
script>
body>
html>
不喜欢就是不喜欢不在乎就是不在乎不明白就是不明白不在乎就是·
简单的数据代理的例子
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>何为数据代理title>
head>
<body>
<script type="text/javascript" >
let obj = {x:100}
let obj2 = {y:200}
Object.defineProperty(obj2,'x',{
get(){
return obj.x
},
set(value){
obj.x = value
}
})
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>Vue中的数据代理title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>学校名称:{{name}}h1>
<h2>学校地址:{{address}}h2>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
const vm = new Vue({
el:"#root",
data:{
name:"鲸落",
address:"武汉"
}
})
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件的基本使用title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习h2>
<button @click="showInfo1">点我提示信息1(不传参)button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
},
methods:{
showInfo1(event){
// console.log(event.target.innerText)
// console.log(this) //此处的this是vm
alert('同学你好!')
},
showInfo2(event,number){
console.log(event,number)
// console.log(event.target.innerText)
// console.log(this) //此处的this是vm
alert('同学你好!!')
}
}
})
script>
html>
prevent
阻止事件的默认行为DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件修饰符title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习h2>
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息a>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods:{
showInfo(e){
alert('同学你好!')
// console.log(e.target)
},
}
})
script>
html>
stop
阻止事件冒泡DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件修饰符title>
<style type="text/css">
.demo1{
height: 50px;
background-color: skyblue;
}
style>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息button>
div>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods:{
showInfo(e){
alert('同学你好!')
// console.log(e.target)
},
}
})
script>
html>
提示事件是先捕获再冒泡,而事件的触发是在事件冒泡阶段发生的
完整代码
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>事件修饰符title>
<script type="text/javascript" src="../js/vue.js">script>
<style>
*{
margin-top: 20px;
}
.demo1{
height: 50px;
background-color: skyblue;
}
.box1{
padding: 5px;
background-color: skyblue;
}
.box2{
padding: 5px;
background-color: orange;
}
.list{
width: 200px;
height: 200px;
background-color: peru;
overflow: auto;
}
li{
height: 100px;
}
style>
head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习h2>
<a href="http://www.atguigu.com" @click.prevent="showInfo">点我提示信息a>
<div class="demo1" @click="showInfo">
<button @click.stop="showInfo">点我提示信息button>
<a href="http://www.atguigu.com" @click.stop.prevent="showInfo">点我提示信息a>
div>
<button @click.once="showInfo">点我提示信息button>
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
div>
div>
<div class="demo1" @click.self="showInfo">
<button @click="showInfo">点我提示信息button>
div>
<ul @wheel.passive="demo" class="list">
<li>1li>
<li>2li>
<li>3li>
<li>4li>
ul>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods:{
showInfo(e){
alert('同学你好!')
// console.log(e.target)
},
showMsg(msg){
console.log(msg)
},
demo(){
for (let i = 0; i < 100000; i++) {
console.log('#')
}
console.log('累坏了')
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>键盘事件title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学习h2>
<input type="text" placeholder="按下回车提示输入" @keydown.huiche="showInfo">
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
Vue.config.keyCodes.huiche = 13 //定义了一个别名按键
new Vue({
el:'#root',
data:{
name:'尚硅谷'
},
methods: {
showInfo(e){
// console.log(e.key,e.keyCode)
console.log(e.target.value)
}
},
})
script>
html>
下面是本节要实现的效果,通过不同的方式实现进行比较,最后发现设计计算属性的目的。
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_插值语法实现title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{firstName}}-{{lastName}}span>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_methods实现title>
<script type="text/javascript" src="../js/vue.js">script>
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>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods: {
fullName(){
console.log('@---fullName')
return this.firstName + '-' + this.lastName
}
},
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性实现title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
测试:<input type="text" v-model="x"> <br/><br/>
全名:<span>{{fullName}}span> <br/><br/>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
x:'你好'
},
methods: {
demo(){
}
},
computed:{
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
get(){
console.log('get被调用了')
// console.log(this) //此处的this是vm 是vue帮我们调成这样的
return this.firstName + '-' + this.lastName
},
//set什么时候调用? 当fullName被修改时。
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_计算属性实现title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}span> <br/><br/>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
},
//当确定了只读取,不修改的话就可以写成下面的简写方式
computed:{
//完整写法
/* fullName:{
get(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
},
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
} */
//简写
fullName(){
console.log('get被调用了')
return this.firstName + '-' + this.lastName
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>今天天气很{{info}}h2>
<button @click="changeWeather">切换天气button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_监视属性title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>今天天气很{{info}}h2>
<button @click="changeWeather">切换天气button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
/* watch:{
isHot:{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}
} */
})
vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_深度监视title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>今天天气很{{info}}h2>
<button @click="changeWeather">切换天气button>
<hr/>
<h3>a的值是:{{numbers.a}}h3>
<button @click="numbers.a++">点我让a+1button>
<h3>b的值是:{{numbers.b}}h3>
<button @click="numbers.b++">点我让b+1button>
<button @click="numbers = {a:666,b:888}">彻底替换掉numbersbutton>
{{numbers.c.d.e}}
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
numbers:{
a:1,
b:1,
c:{
d:{
e:100
}
}
}
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
isHot:{
// immediate:true, //初始化时让handler调用一下
//handler什么时候调用?当isHot发生改变时。
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
},
//监视多级结构中某个属性的变化
/* 'numbers.a':{
handler(){
console.log('a被改变了')
}
} */
//监视多级结构中所有属性的变化
numbers:{
deep:true,
handler(){
console.log('numbers改变了')
}
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>天气案例_监视属性_简写title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>今天天气很{{info}}h2>
<button @click="changeWeather">切换天气button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{
//正常写法
/* isHot:{
// immediate:true, //初始化时让handler调用一下
// deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}, */
//简写
/* isHot(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue,this)
} */
}
})
//正常写法
/* vm.$watch('isHot',{
immediate:true, //初始化时让handler调用一下
deep:true,//深度监视
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
}
}) */
//简写
/* vm.$watch('isHot',(newValue,oldValue)=>{
console.log('isHot被修改了',newValue,oldValue,this)
}) */
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>姓名案例_watch实现title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
姓:<input type="text" v-model="firstName"> <br/><br/>
名:<input type="text" v-model="lastName"> <br/><br/>
全名:<span>{{fullName}}span> <br/><br/>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
watch:{
firstName(val){
setTimeout(()=>{
console.log(this)
this.fullName = val + '-' + this.lastName
},1000);
},
lastName(val){
this.fullName = this.firstName + '-' + val
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>绑定样式title>
<style>
.basic{
width: 400px;
height: 100px;
border: 1px solid black;
}
.happy{
border: 4px solid red;;
background-color: rgba(255, 255, 0, 0.644);
background: linear-gradient(30deg,yellow,pink,orange,yellow);
}
.sad{
border: 4px dashed rgb(2, 197, 2);
background-color: gray;
}
.normal{
background-color: skyblue;
}
.atguigu1{
background-color: yellowgreen;
}
.atguigu2{
font-size: 30px;
text-shadow:2px 2px 10px red;
}
.atguigu3{
border-radius: 20px;
}
style>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<div class="basic" :class="mood" @click="changeMood">{{name}}div> <br/><br/>
<div class="basic" :class="classArr">{{name}}div> <br/><br/>
<div class="basic" :class="classObj">{{name}}div> <br/><br/>
<div class="basic" :style="styleObj">{{name}}div> <br/><br/>
<div class="basic" :style="styleArr">{{name}}div>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
mood:'normal',
classArr:['atguigu1','atguigu2','atguigu3'],
classObj:{
atguigu1:false,
atguigu2:false,
},
styleObj:{
fontSize: '40px',
color:'red',
},
styleObj2:{
backgroundColor:'orange'
},
styleArr:[
{
fontSize: '40px',
color:'blue',
},
{
backgroundColor:'gray'
}
]
},
methods: {
changeMood(){
const arr = ['happy','sad','normal']
const index = Math.floor(Math.random()*3)
this.mood = arr[index]
}
},
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>条件渲染title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>当前的n值是:{{n}}h2>
<button @click="n++">点我n+1button>
<template v-if="n === 1">
<h2>你好h2>
<h2>尚硅谷h2>
<h2>北京h2>
template>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
n:0
}
})
script>
html>
v-for指令
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本列表title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>人员列表(遍历数组)h2>
<ul>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}-{{p.age}}
li>
ul>
<h2>汽车信息(遍历对象)h2>
<ul>
<li v-for="(value,k) of car" :key="k">
{{k}}-{{value}}
li>
ul>
<h2>测试遍历字符串(用得少)h2>
<ul>
<li v-for="(char,index) of str" :key="index">
{{char}}-{{index}}
li>
ul>
<h2>测试遍历指定次数(用得少)h2>
<ul>
<li v-for="(number,index) of 5" :key="index">
{{index}}-{{number}}
li>
ul>
div>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
persons:[
{id:'001',name:'张三',age:18},
{id:'002',name:'李四',age:19},
{id:'003',name:'王五',age:20}
],
car:{
name:'奥迪A8',
price:'70万',
color:'黑色'
},
str:'hello'
}
})
script>
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>用于检测title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<ul>
<h2>人员列表h2>
<button @click.once="add">添加一个老刘button>
<li v-for="(p,index) of persons" :key="index">
{{p.name}}-{{p.age}}
<input type="text">
li>
ul>
div>
<script>
Vue.config.productionTip = false
new Vue({
el:"#root",
data:{
persons:[
{id:'001',name:'张三',age:12},
{id:'002',name:'李四',age:12},
{id:'003',name:'王五',age:12}
]
},
methods: {
add(){
const p = {id:'004',name:'老刘',age:40};
this.persons.unshift(p); //往前面添加
}
},
})
script>
body>
html>
对上面的代码进行标记
运行结果
当在每一个输入框中输入内容的时候
这个时候点击按钮,会看到
接下来,改一下
下面显示正常,没有错位了
详细原理如下
使用index作为key
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>列表过滤title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<ul>
<h2>人员列表h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<li v-for="(p,index) in filpersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
li>
ul>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
//方式一: 用watch实现
new Vue({
el:"#root",
data:{
keyWord:"", //刚开始的时候为空
persons:[
{id:'001',name:'马冬梅',age:12,sex:'女'},
{id:'002',name:'周冬雨',age:22,sex:'女'},
{id:'003',name:'周杰伦',age:34,sex:'男'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
],
filpersons:[]
},
watch:{
keyWord:{
immediate:true, //可以走来就执行一次
handler(val){
this.filpersons = this.persons.filter((p)=>{
return p.name.indexOf(val) !== -1;
})
}
}
}
})
script>
body>
html>
代码分析
知识回顾
filter
过滤器
indexof
数组的一个方法
没有的就返回-1,
注意:空格也是返回-1
这个方法比上面有watch要好一点,简单一点
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>列表过滤title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<ul>
<h2>人员列表h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<li v-for="(p,index) in filpersons" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
li>
ul>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
//方式一: 用watch实现
new Vue({
el:"#root",
data:{
keyWord:"", //刚开始的时候为空
persons:[
{id:'001',name:'马冬梅',age:12,sex:'女'},
{id:'002',name:'周冬雨',age:22,sex:'女'},
{id:'003',name:'周杰伦',age:34,sex:'男'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
],
},
computed:{ //刚开始的时候就会执行一次 数据改变的时候也会执行
filpersons(){
return this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !==-1;
})
}
}
})
script>
body>
html>
首先先回顾一下数组中的sort
方法,sort会改变原来的数组
详细教程sort方法文档
举例子
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
// 如果数组是数字的话,就需要在方法里面的函数里面传入两个参数
let arr = [1,4,3,2];
// 根据a-b还是b-a确定是降序还是升序 默认是降序
arr.sort(function(a,b){
return a-b; //第一参数减去第二参数 升序
})
console.log(arr);
arr.sort((a,b)=>{
return b-a; //第二个参数减去第一个参数 降序
})
console.log(arr);
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>列表排序title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<ul>
<h2>人员列表h2>
<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}}-{{p.sex}}
<input type="text">
li>
ul>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
new Vue({
el:"#root",
data:{
keyWord:"", //刚开始的时候为空
sortType:0, //原顺序是0, 1是降序 2是升序
persons:[
{id:'001',name:'马冬梅',age:12,sex:'女'},
{id:'002',name:'周冬雨',age:22,sex:'女'},
{id:'003',name:'周杰伦',age:34,sex:'男'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
],
},
computed:{
filpersons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !==-1;
})
//判断是否需要排序
if(this.sortType){
arr.sort((p1,p2)=>{ //这里面的p1,p2是对象
return this.sortType ===1? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
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>列表排序title>
<script src="../js/vue.js">script>
head>
<body>
<div id="root">
<ul>
<h2>人员列表h2>
<button @click="updataMei">更新马冬梅的信息button>
<li v-for="(p,index) in persons" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
li>
ul>
div>
<script>
Vue.config.productionTip = false //以阻止 vue 在启动时生成生产提示
const vm = new Vue({
el:"#root",
data:{
persons:[
{id:'001',name:'马冬梅',age:12,sex:'女'},
{id:'002',name:'周冬雨',age:22,sex:'女'},
{id:'003',name:'周杰伦',age:34,sex:'男'},
{id:'004',name:'温兆伦',age:21,sex:'男'}
]
},
methods: {
updataMei(){
/* this.persons[0].name = '马老师',
this.persons[0].age = 50,
this.persons[0].sex = '男' */ //上面的可以成功,但是太麻烦了
this.persons[0] ={id:'001',name:'马老师',age:59,sex:'男'}
}
},
})
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Vue监测数据改变的原理title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
const vm = new Vue({
el:'#root',
data:{
name:'尚硅谷',
address:'北京',
student:{
name:'tom',
age:{
rAge:40,
sAge:29,
},
friends:[
{name:'jerry',age:35}
]
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Documenttitle>
head>
<body>
<script type="text/javascript" >
let data = {
name:'尚硅谷',
address:'北京',
}
//创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data)
console.log(obs)
//准备一个vm实例对象
let vm = {}
vm._data = data = obs
function Observer(obj){
//汇总对象中所有的属性形成一个数组
const keys = Object.keys(obj)
//遍历
keys.forEach((k)=>{
Object.defineProperty(this,k,{
get(){
return obj[k]
},
set(val){
console.log(`${k}被改了,我要去解析模板,生成虚拟DOM.....我要开始忙了`)
obj[k] = val
}
})
})
}
script>
body>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>收集表单数据title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<form @submit.prevent="demo">
账号:<input type="text" v-model.trim="userInfo.account"> <br/><br/>
密码:<input type="password" v-model="userInfo.password"> <br/><br/>
年龄:<input type="number" v-model.number="userInfo.age"> <br/><br/>
性别:
男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
女<input type="radio" name="sex" v-model="userInfo.sex" value="female"> <br/><br/>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
<br/><br/>
所属校区
<select v-model="userInfo.city">
<option value="">请选择校区option>
<option value="beijing">北京option>
<option value="shanghai">上海option>
<option value="shenzhen">深圳option>
<option value="wuhan">武汉option>
select>
<br/><br/>
其他信息:
<textarea v-model.lazy="userInfo.other">textarea> <br/><br/>
<input type="checkbox" v-model="userInfo.agree">阅读并接受<a href="http://www.atguigu.com">《用户协议》a>
<button>提交button>
form>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
userInfo:{
account:'',
password:'',
age:18,
sex:'female',
hobby:[],
city:'beijing',
other:'',
agree:''
}
},
methods: {
demo(){
console.log(JSON.stringify(this.userInfo))
}
}
})
script>
html>
这个不常用
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-text指令title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<div>你好,{{name}}div>
<div v-text="name">div>
<div v-text="str">div>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷',
str:'你好啊!
'
}
})
script>
html>
视频大概26分钟,看了4分钟,到时候需要的时候再看
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-html指令title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<div>你好,{{name}}div>
<div v-html="str">div>
<div v-html="str2">div>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷',
str:'你好啊!
',
str2:'兄弟我找到你想要的资源了,快来!',
}
})
script>
html>
先跳过
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-cloak指令title>
<style>
[v-cloak]{
display:none;
}
style>
head>
<body>
<div id="root">
<h2 v-cloak>{{name}}h2>
div>
<script type="text/javascript" src="http://localhost:8080/resource/5s/vue.js">script>
body>
<script type="text/javascript">
console.log(1)
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
name:'尚硅谷'
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-once指令title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2 v-once>初始化的n值是:{{n}}h2>
<h2>当前的n值是:{{n}}h2>
<button @click="n++">点我n+1button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
n:1
}
})
script>
html>
这个就是程序员写的是就是什么,不关vue的事
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>v-pre指令title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2 v-pre>Vue其实很简单h2>
<h2 >当前的n值是:{{n}}h2>
<button @click="n++">点我n+1button>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
n:1
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>自定义指令title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2>{{name}}h2>
<h2>当前的n值是:<span v-text="n">span> h2>
<h2>放大10倍后的n值是:<span v-big="n">span> h2>
<button @click="n++">点我n+1button>
<hr/>
<input type="text" v-fbind:value="n">
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义全局指令
/* Vue.directive('fbind',{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
}) */
new Vue({
el:'#root',
data:{
name:'尚硅谷',
n:1
},
directives:{
//big函数何时会被调用?1.指令与元素成功绑定时(一上来)。2.指令所在的模板被重新解析时。
/* 'big-number'(element,binding){
// console.log('big')
element.innerText = binding.value * 10
}, */
big(element,binding){
console.log('big',this) //注意此处的this是window
// console.log('big')
element.innerText = binding.value * 10
},
fbind:{
//指令与元素成功绑定时(一上来)
bind(element,binding){
console.log(element,binding);
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding){
element.value = binding.value
}
}
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Documenttitle>
<style>
.demo{
background-color: orange;
}
style>
head>
<body>
<button id="btn">点我创建一个输入框button>
<script type="text/javascript" >
const btn = document.getElementById('btn')
btn.onclick = ()=>{
const input = document.createElement('input')
input.className = 'demo'
input.value = 99
input.onclick = ()=>{alert(1)}
document.body.appendChild(input)
input.focus()
// input.parentElement.style.backgroundColor = 'skyblue'
console.log(input.parentElement)
}
script>
body>
html>
到时候有时间再看
需求,一开始就让页面的文字得到透明度逐渐发生变化,而不是通过点击或者触发。
使用方法的实现的话
用这个,不要将定时器写再方法中,可能会导致无限的调用,造成不必要的麻烦
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>引出生命周期title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h2 v-if="a">你好啊h2>
<h2 :style="{opacity}">欢迎学习Vueh2>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
new Vue({
el:'#root',
data:{
a:false,
opacity:1
},
methods: {
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后(挂载完毕)调用mounted
mounted(){
console.log('mounted',this)
setInterval(() => {
this.opacity -= 0.01
if(this.opacity <= 0) this.opacity = 1
},16)
},
})
//通过外部的定时器实现(不推荐)
/* setInterval(() => {
vm.opacity -= 0.01
if(vm.opacity <= 0) vm.opacity = 1
},16) */
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>基本使用title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<hello>hello>
<hr>
<h1>{{msg}}h1>
<hr>
<school>school>
<hr>
<student>student>
div>
<div id="root2">
<hello>hello>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//第一步:创建school组件
const school = Vue.extend({
template:`
学校名称:{{schoolName}}
学校地址:{{address}}
`,
// el:'#root', //组件定义时,一定不要写el配置项,因为最终所有的组件都要被一个vm管理,由vm决定服务于哪个容器。
data(){
return {
schoolName:'尚硅谷',
address:'北京昌平'
}
},
methods: {
showName(){
alert(this.schoolName)
}
},
})
//第一步:创建student组件
const student = Vue.extend({
template:`
学生姓名:{{studentName}}
学生年龄:{{age}}
`,
data(){
return {
studentName:'张三',
age:18
}
}
})
//第一步:创建hello组件
const hello = Vue.extend({
template:`
你好啊!{{name}}
`,
data(){
return {
name:'Tom'
}
}
})
//第二步:全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步:注册组件(局部注册)
components:{
school,
student
}
})
new Vue({
el:'#root2',
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>几个注意点title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>{{msg}}h1>
<school>school>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义组件
const s = Vue.extend({
name:'atguigu',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
}
})
new Vue({
el:'#root',
data:{
msg:'欢迎学习Vue!'
},
components:{
school:s
}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>组件的嵌套title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//定义student组件
const student = Vue.extend({
name:'student',
template:`
学生姓名:{{name}}
学生年龄:{{age}}
`,
data(){
return {
name:'尚硅谷',
age:18
}
}
})
//定义school组件
const school = Vue.extend({
name:'school',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
//注册组件(局部)
components:{
student
}
})
//定义hello组件
const hello = Vue.extend({
template:`{{msg}}
`,
data(){
return {
msg:'欢迎来到尚硅谷学习!'
}
}
})
//定义app组件
const app = Vue.extend({
template:`
`,
components:{
school,
hello
}
})
//创建vm
new Vue({
template:' ',
el:'#root',
//注册组件(局部)
components:{app}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>组件的嵌套title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//定义student组件
const student = Vue.extend({
name:'student',
template:`
学生姓名:{{name}}
学生年龄:{{age}}
`,
data(){
return {
name:'尚硅谷',
age:18
}
}
})
//定义school组件
const school = Vue.extend({
name:'school',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
//注册组件(局部)
components:{
student
}
})
//定义hello组件
const hello = Vue.extend({
template:`{{msg}}
`,
data(){
return {
msg:'欢迎来到尚硅谷学习!'
}
}
})
//定义app组件
const app = Vue.extend({
template:`
`,
components:{
school,
hello
}
})
//创建vm
new Vue({
template:' ',
el:'#root',
//注册组件(局部)
components:{app}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>VueComponenttitle>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<school>school>
<hello>hello>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false
//定义school组件
const school = Vue.extend({
name:'school',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods: {
showName(){
console.log('showName',this)
}
},
})
const test = Vue.extend({
template:`atguigu`
})
//定义hello组件
const hello = Vue.extend({
template:`
{{msg}}
`,
data(){
return {
msg:'你好啊!'
}
},
components:{test}
})
// console.log('@',school)
// console.log('#',hello)
//创建vm
const vm = new Vue({
el:'#root',
components:{school,hello}
})
script>
html>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>一个重要的内置关系title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<school>school>
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
Vue.prototype.x = 99
//定义school组件
const school = Vue.extend({
name:'school',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'尚硅谷',
address:'北京'
}
},
methods: {
showX(){
console.log(this.x)
}
},
})
//创建一个vm
const vm = new Vue({
el:'#root',
data:{
msg:'你好'
},
components:{school}
})
//定义一个构造函数
/* function Demo(){
this.a = 1
this.b = 2
}
//创建一个Demo的实例对象
const d = new Demo()
console.log(Demo.prototype) //显示原型属性
console.log(d.__proto__) //隐式原型属性
console.log(Demo.prototype === d.__proto__)
//程序员通过显示原型属性操作原型对象,追加一个x属性,值为99
Demo.prototype.x = 99
console.log('@',d) */
script>
html>
一个标准的单文件组件
School.vue
文件
<template>
<div class="demo">
<h2>学校名称:{{ schoolName }}h2>
<h2>学校地址:{{ address }}h2>
<button @click="showName">点我提示学校名button>
div>
template>
<script>
export default ({ //为了可以让其它的文件可以引用 一般都喜欢用默认暴露
name:'School', //最好和文件名保持一致
data() {
return {
schoolName: "尚硅谷",
address: "北京昌平",
};
},
methods: {
showName() {
alert(this.schoolName);
},
},
});
script>
<style>
.demo{
background-color: aqua;
}
style>
index.htm
文件
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>联系一下单组件的写法title>
head>
<body>
<div id="root">
div>
<script src="../js/vue.js">script>
<script src="./main.js">script>
body>
html>
main.js
文件
import App from './School.vue'
new Vue({
el:"#root",
template:`<App>App>`,
components:{
App
}
})
School.vue
文件
<template>
<div class="demo">
<h2>学校名称:{{ schoolName }}h2>
<h2>学校地址:{{ address }}h2>
<button @click="showName">点我提示学校名button>
div>
template>
<script>
export default ({ //为了可以让其它的文件可以引用 一般都喜欢用默认暴露
name:'School', //最好和文件名保持一致
data() {
return {
schoolName: "尚硅谷",
address: "北京昌平",
};
},
methods: {
showName() {
alert(this.schoolName);
},
},
});
script>
<style>
.demo{
background-color: aqua;
}
style>
Student.vue
文件
<template>
<div class="demo">
<h2>学生姓名:{{ name }}h2>
<h2>学生年龄:{{ age }}h2>
div>
template>
<script>
export default ({
name:'School',
data() {
return {
name: "鲸落",
age: 45,
};
},
});
script>
├── 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:包版本控制文件
/*
该文件是整个项目的入口文件
*/
//引入Vue
import Vue from 'vue'
//引入App组件,它是所有组件的父组件
import App from './App.vue'
//关闭vue的生产提示
Vue.config.productionTip = false
/*
关于不同版本的Vue:
1.vue.js与vue.runtime.xxx.js的区别:
(1).vue.js是完整版的Vue,包含:核心功能+模板解析器。
(2).vue.runtime.xxx.js是运行版的Vue,只包含:核心功能;没有模板解析器。
2.因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用
render函数接收到的createElement函数去指定具体内容。
*/
//创建Vue实例对象---vm
new Vue({
el:'#app',
//render函数完成了这个功能:将App组件放入容器中
render: h => h(App),
// render:q=> q('h1','你好啊')
// template:`你好啊
`,
// components:{App},
})
.....
或
this.$refs.xxx
本节用到的文件如下
简单的父组件给子组件传值的方式
本节用到是上面的两个文件
StudentStudent.vue
文件
<template>
<div class="demo">
<h1>{{msg}}h1>
<h2>学校的名称:{{name}}h2>
<h2>学校地址:{{sex}}h2>
<h2>学生年龄:{{age+22}}h2>
div>
template>
<script>
export default {
name:'StudentStudent',
data() {
return {
msg:"我是一个优秀的学生"
}
},
props:["name","sex","age"]
}
script>
<style>
.demo{
background-color: aquamarine;
}
style>
App.vue
文件
<template>
<div>
<StudentStudent name="小白" sex="女" age="22"/>
<StudentStudent name="李百" sex="男" :age="55"/>
div>
template>
<script>
// 引入school组件
import StudentStudent from './components/StudentStudent'
export default {
name:'App',
components:{StudentStudent},
}
script>
<style>
style>
运行结果
限制类型的方式
更高端的方式
总结
props配置项
功能:让组件接收外部传过来的数据
传递数据:
接收数据:
第一种方式(只接收):props:['name']
第二种方式(限制类型):props:{name:String}
第三种方式(限制类型、限制必要性、指定默认值):
props:{
name:{
type:String, //类型
required:true, //必要性
default:'老王' //默认值
}
}
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
为什么要引入混合
如下图代码
有重复的部分,看起来很不舒服
所以有必要将它们合在一起不是更好
所以就有了这个概念
总结:
功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
第一步定义混合:
{
data(){....},
methods:{....}
....
}
第二步使用混入:
全局混入:Vue.mixin(xxx)
局部混入:mixins:['xxx']
<template>
<div class="todo-footer">
<label>
<input type="checkbox"/>
label>
<span>
<span>span> / 全部
span>
<button class="btn btn-danger">清除已完成任务button>
div>
template>
<script>
export default {
name:'MyFooter',
}
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>
<template>
<div class="todo-header">
<input type="text" placeholder="请输入你的任务名称,按回车键确认"/>
div>
template>
<script>
export default {
name:'MyHeader',
}
script>
<style scoped>
/*header*/
.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>
<template>
<li>
<label>
<input type="checkbox"/>
<span>{{todo.title}}span>
label>
<button>删除button>
li>
template>
<script>
export default {
name:'MyItem',
// 声明接收的todo对象
props:['todo'],
}
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>
<template>
<ul class="todo-main">
<MyItem v-for="todoObj in todos" :key="todoObj.id" :todo="todoObj"/>
ul>
template>
<script>
import MyItem from './MyItem'
export default {
name:'MyList',
components:{MyItem},
data() {
return {
todos:[
{id:'0001',title:'吃饭',deno:true},
{id:'0002',title:'喝酒',deno:false},
{id:'0003',title:'开车',deno:true},
]
}
},
}
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>
<template>
<div id="root">
<div class="todo-container">
<div class="todo-wrap">
<MyHeader/>
<MyList/>
<MyFooter/>
div>
div>
div>
template>
<script>
import MyHeader from './components/MyHeader'
import MyList from './components/MyList'
import MyFooter from './components/MyFooter.vue'
export default {
name:'App', //自己的名字
components:{MyHeader,MyList,MyFooter},
}
script>
<style>
/*base*/
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>
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false
//创建vm
new Vue({
el:'#app',
render: h => h(App)
})
需求:在在输入框中输入内容的时候,按回车就会把内容添加到列表里面。
第一阶段在输入框中输入内容
运行结果
拓展
在本节需要使用到id,因此引入了一个库,它可以随机的生成不重复的id
导入它的方式:
总结:在这里面实现了输入并存放数据的功能,本节主要使用知识点有
@keyup.enter="add"
通过点击键盘中的每一个键触发,这里使用的是回车键e.target.value
获取输入框输入的值id
库nanoid
的下载和使用
本次动了下面的三个文件
Myheader.vue
Mylist.vue
App.vue
App.vue
将数据通过props传给Mylist.vue
组件,然后App.vue
组件通过传递一个函数给Myheader.vue
通过参数的方式得到它输入的数据
Mylist.vue
App.vue
Myheader.vue
上面传递成功了
MyHeader.vue
组件变化的地方
·
App.vue
变化的地方
App.vue
变化的地方
MyList.vue
变数的地方
MyItem.vue
组件变化的地方
运行结果
没有点击之前的状态
点击之后的状态
MyItem.vue
组件的变化
MyList.vue组件
的变化
App.vue
组件的变化
本节会用到reduce这个方法reduce的回顾
reduce这个方法作用在数组上,数组有几条数据就会执行几次
pre第一次的值为后面给的第二个参数0,第二个参数为第一次的返回值
有于没有写retrun语句,所以后面的两个值都是未定义
当给一个返回值的时候
current为每一个数组的每一个项
进入到正题
App.vue
改变的地方
MyFooter.vue
改变的地方
运行结果
实现了上面全部勾选上的时候下面的全选按钮就会被勾选上
勾选下面的按钮,上面的按钮会全部被勾选
底部的全部清除功能
组件化编码流程:
(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
(2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
1).一个组件在用:放在组件自身即可。
2). 一些组件在用:放在他们共同的父组件上(状态提升)。
(3).实现交互:从绑定事件开始。
props适用于:
(1).父组件 ==> 子组件 通信
(2).子组件 ==> 父组件 通信(要求父先给子一个函数)
使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。
存数据
DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>localStoragetitle>
head>
<body>
<h2>localStorageh2>
<button onclick="saveData()">点我保存一个数据button>
body>
<script type="text/javascript">
let p = {name:'张三',age:13}
function saveData(){
localStorage.setItem('msg','hello!!!')
localStorage.setItem('msg2',666)
localStorage.setItem('person',JSON.stringify(p))//将一个对象装换成一个字符串并且可以正常的显示
}
script>
html>
session
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>sessionStoragetitle>
head>
<body>
<h2>sessionStorageh2>
<button onclick="saveData()">点我保存一个数据button>
<button onclick="readData()">点我读取一个数据button>
<button onclick="deleteData()">点我删除一个数据button>
<button onclick="deleteAllData()">点我清空一个数据button>
<script type="text/javascript" >
let p = {name:'张三',age:18}
function saveData(){
sessionStorage.setItem('msg','hello!!!')
sessionStorage.setItem('msg2',666)
sessionStorage.setItem('person',JSON.stringify(p))
}
function readData(){
console.log(sessionStorage.getItem('msg'))
console.log(sessionStorage.getItem('msg2'))
const result = sessionStorage.getItem('person')
console.log(JSON.parse(result))
// console.log(sessionStorage.getItem('msg3'))
}
function deleteData(){
sessionStorage.removeItem('msg2')
}
function deleteAllData(){
sessionStorage.clear()
}
script>
body>
html>
总结
webStorage
存储内容大小一般支持5MB左右(不同浏览器可能还不一样)
浏览器端通过 Window.sessionStorage 和 Window.localStorage 属性来实现本地存储机制。
相关API:
xxxxxStorage.setItem('key', 'value');
该方法接受一个键和值作为参数,会把键值对添加到存储中,如果键名存在,则更新其对应的值。
xxxxxStorage.getItem('person');
该方法接受一个键名作为参数,返回键名对应的值。
xxxxxStorage.removeItem('key');
该方法接受一个键名作为参数,并把该键名从存储中删除。
xxxxxStorage.clear()
该方法会清空存储中的所有数据。
备注:
xxxxxStorage.getItem(xxx)
如果xxx对应的value获取不到,那么getItem的返回值是null。JSON.parse(null)
的结果依然是null。这个是为了区别内置事件而产生的
本节用到三个文件
School.vue
文件
<template>
<div class="school">
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
template>
<script>
export default {
name:'School',
data() {
return {
name:'尚硅谷',
address:'北京',
}
},
}
script>
<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
style>
Student.vue
文件
<template>
<div class="student">
<h2>学生姓名:{{name}}h2>
<h2>学生性别:{{sex}}h2>
div>
template>
<script>
export default {
name:'Student',
data() {
return {
name:'张三',
sex:'男'
}
},
}
script>
<style lang="less" scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
style>
app.vue
<template>
<div class="app">
<h1>{{msg}}h1>
<School/>
<Student/>
div>
template>
<script>
import Student from './components/Student'
import School from './components/School'
export default {
name:'App',
components:{School,Student},
data(){
return{
msg:"你好啊"
}
}
}
script>
<style scoped>
.app{
background-color: gray;
padding: 5px;
}
style>
父给子传递函数的方式获取子的数据(这是之前用到过的)为了和下面的形成对比
下面通过app.vue和Student.vue
文件将下面的组件的自定义事件
App.vue
文件
Student.vue
文件
第二种方式,比第一种更加的灵活
如果想要传多个值的话
student.vue
app.vue
组件绑定原生的事件
会放在最外侧的那一个大的div
,所以这就是只要一个根元素的原因之一
总结
一种组件间通信的方式,适用于:子组件 ===> 父组件
使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
绑定自定义事件:
第一种方式,在父组件中:
或
第二种方式,在父组件中:
<Demo ref="demo"/>
......
mounted(){
this.$refs.xxx.$on('atguigu',this.test)
}
若想让自定义事件只能触发一次,可以使用once
修饰符,或$once
方法。
将App.vue
组件子组件header.vue
通过自定义事件的方式拿到子组件的数据
一种组件间通信的方式,适用于任意组件间通信。
安装全局事件总线:
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
},
......
})
使用事件总线:
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.$bus.$on('xxxx',this.demo)
}
提供数据:this.$bus.$emit('xxxx',数据)
本节改的是App.vue
和MyItemvue
通信的情况
下面两张都是App.vue
MyList.vue
文件
本节需要用到的库
pubsub.js
他是subscript和publish的简写(在任何一个框架里面都可以实现消息的发布和订阅
)
先安装这个库
本节可以通过消息订阅的方式实现两个组件的通信
student.vue
== 消息订阅与发布(pubsub)==
一种组件间通信的方式,适用于任意组件间通信。
使用步骤:
安装pubsub:npm i pubsub-js
引入: import pubsub from 'pubsub-js'
接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.pid = pubsub.subscribe('xxx',this.demo) //订阅消息
}
提供数据:pubsub.publish('xxx',数据)
最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)
去取消订阅。
<template>
<div>
<button @click="isShow =!isShow">显示/隐藏button>
<transition>
<h1 v-show="isShow">你好啊!h1>
transition>
div>
template>
<script>
export default {
data(){
return {
isShow:true
}
},
}
script>
<style>
h1{
background-color: orange;
}
.v-enter-active{
animation: atguigu 1s;
}
.v-leave-active{
animation: atguigu 1s reverse;
}
@keyframes atguigu{
from{
transform: translateX(-100%);
},
to{
transform: translateX(0px);
}
}
style>
可以让他自己做动画
<template>
<div>
<button @click="isShow = !isShow">显示/隐藏button>
<transition name="hello" appear>
<h1 v-show="isShow">你好啊!h1>
transition>
div>
template>
<script>
export default {
name:'Test2',
data() {
return {
isShow: true,
};
},
};
script>
<style>
h1 {
background-color: orange;
transition: 0.5s linear;
}
/* 进入的起点 */
.hello-enter{
transform: translateX(-100%);
}
/* 进入的终点 */
.hello-enter-to {
transform: translateX(0);
}
/* 离开的起点 */
.hello-leave{
transform: translateX(0);
}
/* 离开的终点 */
.hello-leave-to{
transform: translateX(-100%);
}
style>
剩下的需要的时候再说(以后用到的时候再回来)
不过这种方式的一次只能向一个端口请求数据
在vue.config.js中添加如下配置:
devServer:{
proxy:"http://localhost:5000"
}
说明:
编写vue.config.js配置具体代理规则:
module.exports = {
devServer: {
proxy: {
'/api1': {// 匹配所有以 '/api1'开头的请求路径
target: 'http://localhost:5000',// 代理目标的基础路径
changeOrigin: true,
pathRewrite: {'^/api1': ''}
},
'/api2': {// 匹配所有以 '/api2'开头的请求路径
target: 'http://localhost:5001',// 代理目标的基础路径
changeOrigin: true,
pathRewrite: {'^/api2': ''}
}
}
}
}
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:8080
changeOrigin默认值为true
*/
说明:
要实现的效果如下
目录结构
bootstrap.css
文件的地址为:地址
它的引入地方
上面的第三方的样式库是控制Search.vue
这个组件的
List.vue
<template>
<div class="row">
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://cn.vuejs.org/images/logo.svg"
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://cn.vuejs.org/images/logo.svg"
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://cn.vuejs.org/images/logo.svg"
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://cn.vuejs.org/images/logo.svg"
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
<div class="card">
<a href="https://github.com/xxxxxx" target="_blank">
<img
src="https://cn.vuejs.org/images/logo.svg"
style="width: 100px"
/>
a>
<p class="card-text">xxxxxxp>
div>
div>
template>
<script>
export default {
name: "List",
};
script>
<style scoped>
.album {
min-height: 50rem; /* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
style>
Search.vue
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Usersh3>
<div>
<input
type="text"
placeholder="enter the name you search"
/> <button>Searchbutton>
div>
section>
template>
<script>
export default {
name: "Search",
};
script>
App.vue
<template>
<div class="container">
<Search />
<List />
div>
template>
<script>
import Search from "./components/Search.vue";
import List from "./components/List.vue";
export default {
name: "App",
components: { Search, List },
};
script>
<style>
style>
https://api.github.com/search/users?q=xxx
这个是github官方免费提供的接口
本节在上节的基础上只变了下面的两个文件
<template>
<div class="row">
<div class="card" v-for="user in users" :key="user.login">
<a :href="user.html_url" target="_blank">
<img :src="user.avatar_url" style="width:100px"/>
a>
<p class="card-text">{{user.login}}p>
div>
div>
template>
<script>
export default {
name: "List",
data() {
return {
users:[]
}
},
mounted(){
this.$bus.$on('data1',(users)=>{
this.users = users;
})
},
beforeDestroy(){
this.$bus.$off('data1');
}
};
script>
<style scoped>
.album {
min-height: 50rem; /* Can be removed; just added for demo purposes */
padding-top: 3rem;
padding-bottom: 3rem;
background-color: #f7f7f7;
}
.card {
float: left;
width: 33.333%;
padding: 0.75rem;
margin-bottom: 2rem;
border: 1px solid #efefef;
text-align: center;
}
.card > img {
margin-bottom: 0.75rem;
border-radius: 100px;
}
.card-text {
font-size: 85%;
}
style>
sreach.vue
文件
<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Usersh3>
<div>
<input
type="text"
placeholder="enter the name you search" v-model="keyWord"/>
<button @click="searchUsers">Searchbutton>
div>
section>
template>
<script>
// 导入axios,之前已经下过了
import axios from 'axios'
export default {
name: "Search",
data() {
return {
keyWord:''
}
},
methods:{
// 通过点击按钮向github发送请求
searchUsers(){
// https://api.github.com/search/users?q=xxx github免费提供的接口
axios.get(`https://api.github.com/search/users?q=${this.kayWord}`).then(
response=>{
// console.log("请求成功了",response.data);
console.log(response.data.items);
this.$bus.$emit("data1",response.data.items); //发送数据
},
error=>{
console.log("失败",error.message);
}
)
}
}
};
script>
代码下多写几遍之后再写过来
它在1.0的时候用的比较多
常用的方式
vue-resource
是对于xhr的封装
安装
用到了上面的两个文件夹
App.vue的代码
Appv.ue
<template>
<div class="container">
<Category>
<img src="../public/1.jpg" alt="" />
Category>
<Category>
<ul>
<li v-for="(g, index) in games" :key="index">{{g}}li>
ul>
Category>
<Category>
<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4">video>
Category>
div>
template>
<script>
import Category from "./components/Category";
export default {
name: "App",
components: { Category },
data() {
return {
foods: ["火锅", "烧烤", "小龙虾", "牛排"],
games: ["红色警戒", "穿越火线", "劲舞团", "超级玛丽"],
films: [
"《教父》",
"《拆弹专家》",
"《你好,李焕英》",
"《尚硅谷》",
],
};
},
};
script>
<style scope>
.container {
display: flex;
justify-content: space-around;
}
img {
width: 100%;
height: 120px;
}
video{
width: 100%;
}
style>
category.vue
<template>
<div class="category">
<h3>vvvvh3>
<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现slot>
div>
template>
<script>
export default {
name:'Catsgory'
}
script>
<style>
.category{
width : 200px;
height: 200px;
background-color: skyblue;
}
h3{
text-align: center;
background-color: orange;
}
style>
<template>
<div class="container">
<Category title="美食">
<img slot="center" src="../public/1.jpg" alt="" />
<a class="foot" slot="footer" href="http://www.baidu.com"
>更多美食a
>
Category>
<Category title="游戏">
<ul slot="center">
<li v-for="(g, index) in games" :key="index">{{ g }}li>
ul>
<div slot="footer" class="foot">
<a href="http://www.baidu.com">单机游戏a>
<a href="http://www.baidu.com">网络游戏a>
div>
Category>
<Category title="电影">
<video
controls
src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"
slot="center"
>video>
<template slot="footer">
<div class="foot">
<a href="http://www.baidu.com">经典a>
<a href="http://www.baidu.com">热门a>
<a href="http://www.baidu.com">推荐a>
div>
<h4 slot="footer">欢迎前来观看h4>
template>
Category>
div>
template>
<script>
import Category from "./components/Category";
export default {
name: "App",
components: { Category },
data() {
return {
foods: ["火锅", "烧烤", "小龙虾", "牛排"],
games: ["红色警戒", "穿越火线", "劲舞团", "超级玛丽"],
films: [
"《教父》",
"《拆弹专家》",
"《你好,李焕英》",
"《尚硅谷》",
],
};
},
};
script>
<style scope>
.container,.foot{
display: flex;
justify-content: space-around;
}
img {
width: 100%;
height: 120px;
}
video {
width: 100%;
}
h4 {
text-align: center;
}
style>
category.vue
<template>
<div class="category">
<h3>{{title}}分类h3>
<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现slot>
<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现slot>
div>
template>
<script>
export default {
name:'Category',
props:['title']
}
script>
<style>
.category{
width : 200px;
height: 250px;
background-color: skyblue;
}
h3{
text-align: center;
background-color: orange;
}
style>
<template>
<div class="category">
<h3>{{ title }}分类h3>
<slot :games="games" msg="hello">我是一些默认值,当使用者没有传递具体结构时,我会出现slot>
div>
template>
<script>
export default {
name: "Category",
props: ["title"],
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽']
}
},
};
script>
<style>
.category {
width: 200px;
height: 250px;
background-color: skyblue;
}
h3 {
text-align: center;
background-color: orange;
}
style>
App.vue
<template>
<div class="container">
<Category title="游戏">
<template slot-scope="weijiang">
<ul>
<li v-for="(g, index) in weijiang.games" :key="index">{{ g }}li>
ul>
template>
Category>
<Category title="游戏">
<template slot-scope="weijiang">
<ol>
<li style="color:red" v-for="(g, index) in weijiang.games" :key="index">{{ g }}li>
ol>
<h4>{{weijiang.msg}}h4>
template>
Category>
<Category title="游戏">
<template slot-scope="{games}">
<h4 v-for="(g, index) in games" :key="index">{{ g }}h4>
template>
Category>
div>
template>
<script>
import Category from "./components/Category";
export default {
name: "App",
components: { Category },
};
script>
<style scope>
.container,
.foot {
display: flex;
justify-content: space-around;
}
img {
width: 100%;
height: 120px;
}
video {
width: 100%;
}
h4 {
text-align: center;
}
style>
作用:让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件 。
分类:默认插槽、具名插槽、作用域插槽
使用方式:
默认插槽:
父组件中:
<Category>
<div>html结构1div>
Category>
子组件中:
<template>
<div>
<slot>插槽默认内容...slot>
div>
template>
具名插槽:
父组件中:
<Category>
<template slot="center">
<div>html结构1div>
template>
<template v-slot:footer>
<div>html结构2div>
template>
Category>
子组件中:
<template>
<div>
<slot name="center">插槽默认内容...slot>
<slot name="footer">插槽默认内容...slot>
div>
template>
作用域插槽:
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
具体编码:
父组件中:
<Category>
<template scope="scopeData">
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}li>
ul>
template>
Category>
<Category>
<template slot-scope="scopeData">
<h4 v-for="g in scopeData.games" :key="g">{{g}}h4>
template>
Category>
子组件中:
<template>
<div>
<slot :games="games">slot>
div>
template>
<script>
export default {
name:'Category',
props:['title'],
//数据在子组件自身
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽']
}
},
}
script>