vue实训练习报告
Vue安装步骤
vue官网:https://cn.vuejs.org/guide/quick-start.html
标签引入方式
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
npm安装方式
- 首先保证安装并配置了node.js环境
- 在命令行终端使用npm命令安装:
npm install vue@2
(指定安装vue2)
Vue指令练习
v-html
在vue中使用插值语法可以动态绑定数据,最常用的形式是双大括号的文本插值。
<span>Message: {{ msg }}</span>
Mustache 标签将会被替代为对应数据对象上 msg
property 的值。无论何时,绑定的数据对象上 msg
property 发生了改变,插值处的内容都会更新。
双大括号会将数据解释为普通文本,而非 HTML 代码。为了输出真正的 HTML,你需要使用v-html指令:
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
v-bind
v-bind
指令用于响应式更新html元素的属性,将一个或多个属性或者一个组件的prop动态绑定到表达式。
例如:v-bind:src="xxx"
简写形式为::src="xxx"
示例代码:
<template>
<div id="app">
<img :src="src" alt="">
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
src:'https://raw.githubusercontent.com/aalyh/Picture/main/20230709161731.jpg'
}
},
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
},
}
</script>
运行结果:
该代码动态绑定了一个src值给img标签,当src的值变化时标签内容同时变化,实现一个响应式更新。
在标签中绑定css样式时也常常使用v-bind指令,例如:
<div :style="{display:'inline-block',width:'200px',height:'200px',backgroundColor:'red'}"></div>
标签中的css表达式写法应采用小驼峰命名。
执行结果:
v-model
v-model
指令与v-bind
指令的区别在于绑定是双向的。常常用于绑定表单数据,实现双向数据绑定。数据不仅可以从data流向页面,还可以从页面流向data。
例如:
<template>
<div id="app">
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
message:'init'
}
}
}
</script>
message初始化的值绑定在页面中,实现数据从data流向页面。当在页面的输入框中改变message的值时,下方绑定的message同时改变,实现数据从页面流向data。
条件渲染
v-if
v-if
指令用于条件性地渲染一块内容。只有当指令的表达式返回值为true
值才会渲染这块内容
练习:
运行该代码
<template>
<div id="app">
<h1>条件指令练习</h1>
<h3>true</h3>
<div v-if="1 === 1">这是返回值为true的结果</div>
<hr>
<h3>false</h3>
<div v-if="1 !== 1">这是返回值为false的结果</div>
</div>
</template>
结果为:
可以看出当v-if的返回值结果为false时,当前内容不在页面上渲染
v-else
v-else
指令是与v-if
搭配使用,v-else
必须紧贴在v-if
之后,否则将不能被识别。
该指令与if-else逻辑相似,当v-if
的表达式结果为false时便执行v-else
指令。
运行下列代码,此时条件判断语句为 info === 5
返回值为true。:
<template>
<div id="app">
<h1>条件指令练习 v-else</h1>
<div v-if="info === 5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
info:5
}
},
}
</script>
此时页面显示的结果为:
当条件返回值为false时:
<template>
<div id="app">
<h1>条件指令练习 v-else</h1>
<div v-if="info === 5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
info:6
}
},
}
</script>
此时页面的渲染结果为:
可以看到结果是v-else
绑定的内容成功渲染。
v-else-if
v-else-if
,顾名思义,充当 v-if
的“else-if 块”,可以连续使用:
类似于 v-else
,v-else-if
也必须紧跟在带 v-if
或者 v-else-if
的元素之后。
执行如下代码:
<template>
<div id="app">
<h1>条件指令练习 v-else</h1>
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'"> B</div>
<div v-else-if="type === 'C'">C</div>
<div v-else> Not A/B/C</div>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
type:'A'
}
},
}
</script>
页面渲染结果为:
可以发现,type === A
的绑定的模块成功渲染。
v-show
该指令也是用于根据条件展示元素。当条件返回结果为true时渲染页面。
不同的是带有 v-show
的元素始终会被渲染并保留在 DOM 中。v-show
只是简单地切换元素的 CSS property display
。
执行如下代码:
<template>
<div id="app">
<h1>条件指令练习 v-else</h1>
<div v-show="true">true</div>
<div v-show="false">false</div>
</div>
</template>
页面渲染结果:
可以看出第一个div被成功渲染。
v-show与v-if的区别
v-if
是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。v-show
不管初始条件是什么,元素总是会被渲染,并且只是简单地基于CSS进行切换v-if
有更高的切换开销,v-show
有更高的初始渲染开销。因此当需要频繁地切换时,使用v-show
较好,如果在运行时条件很少改变,则使用v-if
较好。
列表渲染
v-for遍历数组
我们可以用 v-for
指令基于一个数组来渲染一个列表。v-for
指令需要使用 item in items
形式的特殊语法,其中 items
是源数据数组,而 item
则是被迭代的数组元素的别名。
在 v-for
块中,我们可以访问所有父作用域的 property。v-for
还支持一个可选的第二个参数,即当前项的索引。
在使用v-for时必须绑定一个key值,否则会提示错误。
运行如下代码:
<template>
<div id="app">
<h1>列表渲染练习 v-else</h1>
<div v-for="(item,index) in info" :key="index">{{ item }}</div>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
info:['A','B','C','D']
}
},
}
</script>
页面中得到渲染结果为:
可以看到数组中的每一项都被遍历展示了出来。
v-for遍历对象
v-for
也可以用来遍历一个对象的property
执行以下代码:
<template>
<div id="app">
<li v-for="value in object" :key="value">
{{ value }}
</li>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
object: {
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
}
}
},
}
</script>
得到结果:
页面将object
对象中的每一个属性结果都遍历并渲染到了页面中。
事件处理
监听事件v-on
可以用 v-on
指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
v-on:click="xxx"
的简写形式为@click="xxx"
示例代码:
<template>
<div id="app">
<button v-on:click="counter += 1">Add 1</button>
<p>The button above has been clicked {{ counter }} times.</p>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
counter: 0
}
},
}
</script>
页面渲染结果:
当鼠标点击add按钮时,counter的值会+1,因为使用v-on
在button
上绑定了点击事件click
,因此当鼠标点击触发事件时,执行绑定的语句,实现counter++
然而许多事件处理逻辑会更为复杂,所以直接把 JavaScript 代码写在 v-on
指令中是不可行的。因此 v-on
还可以接收一个需要调用的方法名称。
示例代码:
<template>
<div id="app">
<button v-on:click="greet">Greet</button>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
name: 'Vue.js'
}
},
methods: {
greet: function (event) {
// `this` 在方法里指向当前 Vue 实例
alert('Hello ' + this.name + '!')
// `event` 是原生 DOM 事件
if (event) {
alert(event.target.tagName)
}
}
},
}
</script>
页面渲染结果:
在该代码中使用v-on
绑定了一个click
事件,并且当事件触发时调用greet
方法。
Vue组件练习
组件的定义时实现应用中局部功能代码和资源的集合。优势是可复用性高,简化项目代码,提高运行效率。
组件化:
- 将一个具备完整功能的项目的一部分分割多处使用
- 加快项目的进度
- 可以进行项目的复用
组件注册分为:
全局注册和局部注册
全局注册
语法:
Vue.component('组件名称', { })
,第1个参数是标签名称,第2个参数是一个选项对象。全局组件注册后,任何vue实例都可以用。
例如:
Vue.component('component-a', { /* ... */ })
Vue.component('component-b', { /* ... */ })
Vue.component('component-c', { /* ... */ })
new Vue({ el: '#app' })
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
局部注册
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的无谓的增加。
所以通常我们选择局部注册组件。
例如:
var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
局部注册的组件在其子组件中不可用。
在实际项目中,通常将组件写为一个vue文件,在需要使用组件的页面中通过import引入并局部注册。
例如:
ref属性
- 被用来给元素或子组件注册引用信息(id的替代者)
- 应用在html标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(vc)
- 使用方式:
- 打标识:
<h1 ref="xxx">.....</h1>
或<School ref="xxx"></School>
- 获取:
this.$refs.xxx
- 打标识:
案例代码:
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button ref="btn" @click="showDOM">点我输出上方的DOM元素</button>
<School ref="sch"/>
</div>
</template>
<script>
//引入School组件
import School from './components/School'
export default {
name:'App',
components:{School},
data() {
return {
msg:'欢迎学习Vue!'
}
},
methods: {
showDOM(){
console.log(this.$refs.title) //真实DOM元素
console.log(this.$refs.btn) //真实DOM元素
console.log(this.$refs.sch) //School组件的实例对象(vc)
}
},
}
</script>
props
-
功能:让组件接收外部传过来的数据
-
传递数据:
<Demo name="xxx"/>
-
接收数据:
-
第一种方式(只接收):
props:['name']
-
第二种方式(限制类型):
props:{name:String}
-
第三种方式(限制类型、限制必要性、指定默认值):
props:{ name:{ type:String, //类型 required:true, //必要性 default:'老王' //默认值 } }
备注:props是只读的,Vue底层会监测你对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么请复制props的内容到data中一份,然后去修改data中的数据。
-
示例代码:
父组件给子组件传数据
App.vue
<template>
<div id="app">
<School name="haha" :age="this.age"></School>
</div>
</template>
<script>
import School from './components/School.vue'
export default {
name: 'App',
data () {
return {
age: 360
}
},
components: {
School
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
School.vue
<template>
<div class="demo">
<h2>学校名称:{{ name }}</h2>
<h2>学校年龄:{{ age }}</h2>
<h2>学校地址:{{ address }}</h2>
<button @click="showName">点我提示学校名</button>
</div>
</template>
<script>
export default {
name: "School",
// 最简单的写法:props: ['name', 'age']
props: {
name: {
type: String,
required: true // 必须要传的
},
age: {
type: Number,
required: true
}
},
data() {
return {
address: "西南石油大学",
};
},
methods: {
showName() {
alert(this.name);
},
},
};
</script>
<style>
.demo {
background-color: orange;
}
</style>
在子组件School中通过props配置项接收到了来自App.vue组件中定义的数据。
组件自定义事件
组件自定义事件是一种组件间通信的方式,用于 子组件 ==>父组件
使用场景:
当子组件想传数据给父组件时,在父组件中给子组件绑定自定义事件,事件的回调在父组件中。
示例代码:
App.vue
<template>
<div class="app">
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) -->
<Student @atguigu="getStudentName"/>
</div>
</template>
<script>
import Student from './components/Student'
export default {
name:'App',
components:{Student},
data() {
return {
msg:'你好啊!',
studentName:''
}
},
methods: {
getStudentName(name,...params){
console.log('App收到了学生名:',name,params)
this.studentName = name
}
}
}
</script>
<style scoped>
.app{
background-color: gray;
padding: 5px;
}
</style>
Student.vue
<template>
<div class="student">
<button @click="sendStudentlName">把学生名给App</button>
</div>
</template>
<script>
export default {
name:'Student',
data() {
return {
name:'张三',
}
},
methods: {
sendStudentlName(){
//触发Student组件实例身上的atguigu事件
this.$emit('atguigu',this.name,666,888,900)
}
},
}
</script>
<style lang="less" scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
vue-router
-
安装vue-router,命令:
npm i vue-router
-
应用插件:
Vue.use(VueRouter)
-
编写router配置项:
//引入VueRouter import VueRouter from 'vue-router' //引入Luyou 组件 import About from '../components/About' import Home from '../components/Home' //创建router实例对象,去管理一组一组的路由规则 const router = new VueRouter({ routes:[ { path:'/about', component:About }, { path:'/home', component:Home } ] }) //暴露router export default router
-
实现切换(active-class可配置高亮样式)
<router-link active-class="active" to="/about">About</router-link>
-
指定展示位置
<router-view></router-view>
几个注意点
- 路由组件通常存放在
pages
文件夹,一般组件通常存放在components
文件夹。 - 通过切换,“隐藏”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。
- 每个组件都有自己的
$route
属性,里面存储着自己的路由信息。 - 整个应用只有一个router,可以通过组件的
$router
属性获取到。
多级路由
-
配置路由规则,使用children配置项:
routes:[ { path:'/about', component:About, }, { path:'/home', component:Home, children:[ //通过children配置子级路由 { path:'news', //此处一定不要写:/news component:News }, { path:'message',//此处一定不要写:/message component:Message } ] } ]
-
跳转(要写完整路径):
<router-link to="/home/news">News</router-link>
-
指定展示位置
<router-view></router-view>
编程式路由导航
-
作用:不借助
<router-link>
实现路由跳转,让路由跳转更加灵活 -
具体编码:
//$router的两个API this.$router.push({ name:'xiangqing', params:{ id:xxx, title:xxx } }) this.$router.replace({ name:'xiangqing', params:{ id:xxx, title:xxx } }) this.$router.forward() //前进 this.$router.back() //后退 this.$router.go() //可前进也可后退 参数为正前进反之后退
,
{
path:‘/home’,
component:Home,
children:[ //通过children配置子级路由
{
path:‘news’, //此处一定不要写:/news
component:News
},
{
path:‘message’,//此处一定不要写:/message
component:Message
}
]
}
]
2. 跳转(要写完整路径):
```vue
<router-link to="/home/news">News</router-link>
-
指定展示位置
<router-view></router-view>
编程式路由导航
-
作用:不借助
<router-link>
实现路由跳转,让路由跳转更加灵活 -
具体编码:
//$router的两个API this.$router.push({ name:'xiangqing', params:{ id:xxx, title:xxx } }) this.$router.replace({ name:'xiangqing', params:{ id:xxx, title:xxx } }) this.$router.forward() //前进 this.$router.back() //后退 this.$router.go() //可前进也可后退 参数为正前进反之后退