一、什么是vue?
二、vue的特点
三、实现第一个vue程序
<head>
<!-- 1.引入vue文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<!-- 2.模板字符渲染 -->
<div id="app">
{{message}}
</div>
<script>
// 3.创建vue对象,并设置要渲染的DOM对象和属性
var app = new Vue({
//el只能指定双标签,而且不能指定html和body元素
el: '#app',
//数组的作用范围为el指定的dom元素的内部
data: {
message: 'first vue'
}
})
</script>
</body>
都是标签的属性值
一、v-text
相当于(textContent)默认的写法会替换全部的内容。即我是谁就不显示了。
也可以进行拼串等操作,h2
那个标签只显示first vue~。
<!-- 模板字符渲染 -->
<div id="app">
{{message}}
<h2 v-text="message+'~'">我是谁</h2>
</div>
// 创建vue对象,并设置要渲染的DOM对象和属性
var app = new Vue({
el: '#app',
data: {
message: 'first vue'
}
})
二、v-html
相当于(innerHTML)默认的写法会替换全部的内容。会把内容解析成html再输出
<!-- 模板字符渲染 -->
<div id="app">
{{message}}
<h3 v-html="htmlText"></h3>
</div>
// 创建vue对象,并设置要渲染的DOM对象和属性
var app = new Vue({
el: '#app',
data: {
message: 'first vue',
htmlText: '我是一个链接'
}
})
三、v-on
相当于(on)是用来绑定事件的属性
如果你要在函数中,获取DOM元素然后在修改他。或许你要在Vue只用换一下思维了,因为Vue是数据驱动的所以你只需要获取响应的数据然后更改对应的数据就可以实现更改DOM元素的操作了。
this.键
获取<!-- 模板字符渲染 -->
<button @click='change' id="app">{{message}}</button>
<script>
// 创建vue对象,并设置要渲染的DOM对象和属性
var app = new Vue({
el: '#app',
data: {
message: 'first vue',
},
methods: {
change: function () {
this.message += '~假的'
}
},
})
</script>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ncIO3Nad-1604480025329)(E:%5Cgif%5Cgif%5Cvue%E7%BB%91%E5%AE%9A%E4%BA%8B%E4%BB%B6.gif)]
四、v-show
根据布尔值的真假,在切换显示状态,ture显示、false隐藏
。
期中v-show属性的值也可以写表达式,即最后表达式都会解析为布尔值
原理是修改display:none
,实现隐藏。
<!-- 模板字符渲染 -->
<div id="app">
<button @click='change'>切换显示状态</button>
<button @click='add'>增加年龄</button>
<img src="https://0x9.me/5aiEb" v-show='isTrue'>
<img src="https://0x9.me/kD4pi" v-show='age>=18'>
</div>
<script>
// 创建vue对象,并设置要渲染的DOM对象和属性
var app = new Vue({
el: '#app',
data: {
isTrue: false,
age: 17,
},
methods: {
change: function () {
this.isTrue = !this.isTrue
},
add: function () {
this.age++;
}
},
})
</script>
五、v-if
和v-show
基本用法和用途一样,唯一不同的是v-show
切换的是属性display:nono属性而v-if
是根据true或false添加或移除DOM元素
在实际开发中经常切换显示的用v-show
反之用v-if
六、v-bind
用途:设置元素的属性。
语法:v-bind:属性名=表达式
期中v-bind可以省略,所以也能写成:属性名=表达式
切换class是否生效的方式:
---css
<style>
.active {
border: 10px solid black;
}
</style>
---html
<div id="app">
<img :src="Src" v-bind:title="Title" :class="{active:isTrue}" @click='changeBolen'>
<img :src="Src" v-bind:title="Title" :class="isTrue?'active':''" @click='changeBolen'>
</div>
---js
var app = new Vue({
el: "#app",
data: {
Src: '01.png',
Title: '马里奥',
isTrue: false
},
methods: {
changeBolen: function () {
this.isTrue = !this.isTrue
}
},
})
七、v-for
用途:根据数据生产列表结构,生成的数据可以在本标签中使用也可以在其他标签中使用。例如:title=“data”期中data就是for循环出来的数据
语法:遍历数组:(item,index)in 数据
或item in 数据
。遍历对象:v-for="(value,key,index) in obj
为了提高Vue元素的性能(即更好的区别兄弟节点),我们为循环的项加上属性key,key代表一个唯一值
改变数据页面也会同步的更新上去,这是因为Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。
<div id="app">
<button @click="add">添加数据</button>
<button @click="remove">删除数据</button>
<ul>
<li :key="index" v-for="(data,index) in arry" :title="data">
这是第{{index+1}}个水果:{{data}}
</li>
<h2 v-for="item in obj">{{item.name}}</h2>
</ul>
<script>
var app=new Vue({
el:'#app',
data:{
arry:['苹果','香蕉','桃子','红龙果'],
obj:[{name:'赵建立'},{name:'网极客'}]
},
methods:{
add:function () {
this.obj.push({name:'沃明师'})
},
remove:function () {
this.obj.shift()
}
}
})
</script>
</div>
八、v-on补充
如果要传递event参数,就要在传递的参数的最后一位写上$event
形参代表传递了event参数
在事件后面跟上.修饰符
就可以对事件进行限制了,例如@keyup.enter='函数'
就可以限制按钮在按enter时才触发函数。
具体的事件修饰符https://cn.vuejs.org/v2/api/#v-on
自定义按键修饰符
//keyCodes就是event上键盘按键对应的keycodes值
Vue.config.keyCodes.a=65
<div id="app">
<!--只有按下enter才能触发函数-->
<input type="text" @keyup.enter="say">
<!-- //#event是固定写法 -->
<input type="button" value="按钮" @click="fun(200,'ok',$event)">
<button @click="hangdle">点击 </button>
</div>
<script>
var app = new Vue({
el: '#app',
data: {},
methods: {
fun: function (num, text, event) {
console.log(num);
console.log(text);
console.log(event.target.tagName)
},
say: function () {
alert('你是个帅哥吗~~')
},
hangdle(event) {
console.log(event.target.innerHTML)
}
}
})
</script>
九、v-model(表单双向绑定)
所谓双向绑定就是:表单的数据和data中的数据相关联,一个修改另一个也跟着修改
<!-- v-model的原理是利用v-on和v-bind进行实现的 -->
<div id="app">
<div v-text="msg"></div>
<!-- 对input进行数据绑定和监听input事件修改数据得到的 -->
<input type="text" :value='msg' @input='hangle'>
<!-- 原理简写 -->
<input type="text" :value='msg' @input="msg=$event.target.value">
</div>
<script>
var app = new Vue({
el: '#app',
data: { msg: 'hello' },
methods: {
hangle(event) {
this.msg = event.target.value
}
}
})
</script>
<div id="app">
<input type="text" v-model="message" @keyup.enter="get">
<input type="button" value="修改message" @click="set">
<p>{{message}}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
message: 'first vue'
},
methods:{
get:function () {
console.log(this.message)
},
set:function () {
this.message='修改的值'
}
}
})
</script>
十、 computed(计算属性)
会将计算结果进行缓存,只要this.firstname和lastname变量的内容不改变,就不会重新计算
<div id="app">
<div>{{ fullname }}div>
<h1>{{ reverseWord }}h1>
<h1>循环偶数年龄h1>
<ul>
<li v-for="student in oddStudents">
<h3>{{ student.studentName }}h3>
<h4>{{ student.age }}h4>
li>
ul>
div>
var app = new Vue({
el: "#app",
data: {
firstname: "张",
lastname: "三",
word: "music",
students: [
{
studentName: "小明",
age: 16,
school: "清华"
},
{
studentName: "小黑",
age: 17,
school: "北大"
},
{
studentName: "小红",
age: 18,
school: "浙大"
},
{
studentName: "小樱",
age: 19,
school: "河软"
},
]
},
computed: {
fullname: function(){
// 会将计算结果进行缓存,只要this.firstname和lastname变量的内容不改变,就不会重新计算
return this.firstname + this.lastname
},
reverseWord: {
get: function(){
return this.word.split("").reverse().join("")
},
set: function(val){
this.word = val.split("").reverse().join("")
}
},
oddStudents: function(){
let results = this.students.filter((student,index)=>{
return student.age%2 == 0
})
return results
}
}
})
十一、v-once
只编译一次
<div id="app">
<h1 v-once>{{ msg }}h1>
div>
var app = new Vue({
el: "#app",
data: {
msg: "hello vue",
}
})
app.msg = "hello 前端"
结果还是 hello vue
十二、v-cloak
我们知道在vue在解析
{{message}}
时是先生成再解析,这样就会导致如果网速慢就会看到{{message}}
替换成值的过程,而v-cloak就是用来解决这个问题的
操作步骤
[v-cloak]{
display:none;
}
v-cloak
解决的原理:先隐藏,替换好值后再显示最终的值
十三、v-cloak
如果我们想跳过vue的编译直接显示标签的内容时,使用该标签
<h2 v-pre>{{msg}}</h2>//直接显示{{msg}}
<div id="app">
<form>
<!-- input的数据绑定 -->
<div>
<label for="inputId"></label>
<input type="text" id="inputId" v-model="inputData">
</div>
<!-- 单选框的数据绑定 -->
<div>
<label for="man">男</label>
<input type="radio" id="man" value="1" v-model="gender">
<label for="flmen">女</label>
<input type="radio" id="flmen" value="2" v-model="gender">
</div>
<!-- 多选框的数据绑定 -->
<div>
<span>爱好:</span>
<label for="basketball">篮球</label>
<input type="checkbox" id='basketball' value="篮球" v-model="hobby">
<label for="game">打游戏</label>
<input type="checkbox" id="game" value="打游戏" v-model="hobby">
<label for="milketea">喝奶茶</label>
<input type="checkbox" id="milketea" value="喝奶茶" v-model="hobby">
</div>
<!-- 下拉框的数据绑定 -->
<div>
<!-- 在select中加multiple="true"是表示多选,然后双向绑定的数据也要换成数组 -->
<select v-model="seletData" >
<option value="吃饭">吃饭</option>
<option value="喝水">喝水</option>
<option value="洗澡">洗澡</option>
</select>
</div>
<!-- 多文本框的数据绑定 -->
<div>
<textarea name="" id="" cols="30" rows="10" v-model="textArea"></textarea>
</div>
</form>
</div>
<script>
// 创建vue对象,并设置要渲染的DOM对象和属性
var app = new Vue({
el: '#app',
data: {
inputData: "input数据",
gender:1,
hobby:[],
seletData:"吃饭",
// seletData:['吃饭']
textArea:"textarea"
},
})
语法:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// inserted指当被绑定的元素插入到 DOM 中时调用
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
//注册一个改变input背景颜色的组件
Vue.directive('color',{
bind:function(el,binding){
//binding.value是接受组件参数
el.style.backgroundColor=binging.value
}
})
使用:
<input type='text' v-focus>
//msg为data中绑定的值
<input type='text' v-color='msg'>
上述的指令都是全局指令,而接下来的定义的是局部指令(只能在局部作用域中使用)
局部指令的定义方法不同于全局指令,但是具体的使用和内部逻辑和全局指令一致
表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁
计算属性也会跟着绑定的数据的改变而发生变化
定义:在创建的Vue实例中新增computed对象,对象中再生成计算方法
<div id="app">
<p>{{result}}</p>olleh
</div>
<script>
var app=new Vue({
el:'#app',
data:{
msg:"hello"
},
computed:{
result:function(){
return this.msg.split('').reverse().join('')
}
}
})
</script>
计算属性有缓存功能,如你访问一个计算属性两次,他第二次就会用你第一次执行过的结果,不会去从新调用
而方式是每次都从新调用一次
侦听器主要是用于处理一些计较耗时或者异步操作
侦听器的主要实现的功能是:当绑定的数据变化时就会触发对应的函数
/*
侦听器注册方法
1.在Vue对象中新建一个watch对象
2.在对象中以 dataName:function(){}方式绑定数据
3.期中dataName就是当这个数据改变时而触发对应的函数
4.dataName要对应data中的数据
*/
new Vue({
el:'#app',
data:{
first:'Jin',
last:"lisa",
text:""
},
watch:{
first:function(val){
//val就是first改变的最新值
this.text=val+this.last
},
last:function(val){...}
}
})
主要是用于格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等
<div id="app">
<input type="text" v-model="msg">
<div>{{msg | bigWrite}}</div>
<div :abc="msg|bigWrite">test</div>
<!-- 代参数的filter -->
<div>{{date|format('yyyy-MM-dd')}}</div>
</div>
<script>
<!-- 带参数的filter -->
Vue.filter('format',function (val,arg) {
if(arg=='yyyy-MM-dd'){
var ret=''
ret=val.getFullYear()+'-'+(val.getMonth()+1)+'-'+val.getDate()
return ret
}
})
var app=new Vue({
el:'#app',
data:{
msg:"hello",
date:new Date()
},
filters:{
bigWrite:function (val) {
return val.charAt(0).toUpperCase()+val.slice(1)
}
}
})
</script>
Vue对象的要经历三个周期
我们知道,如果你把data中的数据循环渲染到页面上了,你在用索引的方式去修改视图,改变页面上的数据,确实你的data中的数据是改变了,但是html视图上的数据依然没有改变,这时你就要用修改响应式数据的方法来修改值了
组件就是一个实现独立功能的一个自定义标签,可以重复使用
Vue.component(“组件名称”,{
//组件的数据就是一个函数返回的对象中的数据
data:function(){
return{
count:0
}
},
template:组件模板内容
})
---------------------------------------
<div id="app">
<button-counter></button-counter>
</div>
<script>
Vue.component('button-counter', {
data: function () {
return {
count: 0
}
},
template: '',
methods: {
addCount: function () {
this.count++;
}
},
})
var app = new Vue({ el: '#app' })
</script>
注意事项
局部组件只能在绑定的父组件中使用
其中的组件内容和上述全局组件的生成内容一致
主要是通过父组件通过添加属性值的方式向子组件发送数据,而子组件新生成一个props属性来接受传过来的值
注意事项
在组件模板中设置属性传递数据时,命名要用断横线式而不能用驼峰式
字符串模板没有限制
因为Vue定义的props要遵循单向数据流,所以子组件要,修改父组件传过来的值时,要通过自定义事件的方式传递给父组件,父组件监听子组件的自定义事件并作出相应操作
//其中$emit是子组件向父组件传递的固定书写方式
<button @click='$emit("自定义事件名",传递的值)'></button>
//其中$event是固定写法,就是子组件传递过来的值,传递给函数性形参
<menu-item @自定义事件名="触发的函数名($event)"></menu-item>
兄弟组件之间的交互要借助,事件中心来生成
<div id="app">
<button @click='distory'>销毁事件中心</button>
<big-brother></big-brother>
<brother></brother>
</div>
<script>
//定义事件中心
var Bbm = new Vue()
Vue.component('BigBrother', {
data: function () {
return {
num: 0
}
},
template: ``,
methods: {
hangle() {
//触发兄弟节点的事件
Bbm.$emit('brother-item', 1)
}
},
mounted() {
//模板生成监听事件
Bbm.$on("brothers-item", (val) => {
this.num += val
})
},
})
Vue.component('brother', {
data: function () {
return {
num: 0
}
},
template: ``,
methods: {
hangle() {
//触发兄弟节点的事件
Bbm.$emit('brothers-item', 2)
}
},
mounted() {
//模板生成监听事件
Bbm.$on("brother-item", (val) => {
this.num += val
})
},
})
var app = new Vue({
el: '#app',
data: {},
methods: {
distory() {
Bbm.$off('brothers-item')
Bbm.$off('brother-item')
}
}
})
</script>
标签用于接收在自定义组件中传递过来的内容
一个组件中可以定义多个有名字和无名字的插槽,如果你在使用自定义组件中,传入了对应插槽的属性,他就会插入到对应名字的插槽中
//下面的写法和2.插槽内容的写法能达到一样的目的
//其中template在解析是并不显示,只是一个占位符
<template slot='header'>
<h1>标题内容</h1>
</template>>
<p>主要内容1</p>
<p>主要内容2</p>
<template slot='footer'>
<p>底部信息</p>
</template>>
应用场景:父组件对子组件的内容进行加工处理
<div id="app">
<button-counter :list-data='listData'>
//这个template和参数是固定格式
<template slot-scope="slotProps">
//在这里面就可以通过lotProps.data的方式获取到子组件的值(注data是子组件自定义的值)
<strong v-if="slotProps.data=='小米'">{{slotProps.data}}</strong>
</template>
</button-counter>
</div>
<script>
Vue.component('button-counter', {
props: ['listData'],
template: `
-
{{item}}
`,
})
var app = new Vue({
el: '#app',
data: {
listData: ['ipone', '小米', 'vivo']
}
})
</script>
后端路由:发送不同的url地址返回不同的内容
本质:url地址与服务器资源之间的对应关系
**前端路由:**是根据不同的用户事件显示不同的页面内容
本质:用户事件与事件处理函数之间的对应关系
<div id="app">
<a href="#/zhuye">主页</a>
<a href="#/keji">科技</a>
<a href="#/caiwu">财务</a>
<a href="#/yule">娱乐</a>
//component就是一个展位符,:is是判断哪个自定义模板做执行
<component :is="method"></component>
</div>
<script>
var zhuye = {
template: "主页
"
}
var keji = {
template: "科技
"
}
var caiwu = {
template: "财务
"
}
var yule = {
template: "娱乐
"
}
var app = new Vue({
el: "#app",
data: {
method: "zhuye"
},
components: {
zhuye,
keji,
caiwu,
yule,
}
})
//用于监听前端路由的变化
window.onhashchange = () => {
//location.hash为前端路由变化的值
var url = location.hash.slice(2)
app.method = url
}
</script>
vue-router是一个依赖于vue的前端标准路由组件
具体执行步骤:1.引入文件,2.用router-link
创建标签,3.写模板占位符,4.创建模板,5.创建VueRouter
并配置,6.挂载在vue对象上
<!--0. 引入vue文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<!-- 1.引入vue-router文件 -->
<script src="https://unpkg.com/[email protected]/dist/vue-router.js"></script>
<div id="app">
<!--2. 创建用router-link创建a标签---to是href只不过后面的路径是加#的。例如:#/user -->
<router-link to="/">主页</router-link>
<router-link to="/user">User</router-link>
<router-link to="/song">Song</router-link>
<!--3. 生成模板展位符 -->
<router-view></router-view>
</div>
<script>
//4. 创建模板
var Main = {
template: "主页
"
}
var User = {
template: "User
"
}
var Song = {
template: "Song
"
}
// 5.创建 VueRouter实例并配置对应路由所展示的组件
var router = new VueRouter({
routes: [
{ path: "/", component: Main },
{ path: "/user", component: User },
{ path: "/song", component: Song }
]
})
var app = new Vue({
el: '#app',
//6.挂载router,
router: router,
})
</script>
<div id="app">
<!--2. 创建用router-link创建a标签---to是href只不过后面的路径是加#的。例如:#/user -->
<router-link to="/">主页</router-link>
<router-link to="/user">User</router-link>
<router-link to="/song">Song</router-link>
<!--3. 生成模板展位符 -->
<router-view></router-view>
</div>
<script>
//4. 创建模板
var Main = {
template: "主页
"
}
var User = {
template: "User
"
}
var Tab1 = {
template: "Tab1
"
}
var Tab2 = {
template: "Tab2
"
}
var Song = {
template: `
Song
//生成链接并创建模板占位符
tab1
tab2
`
}
// 5.创建 VueRouter实例并配置对应路由所展示的组件
var router = new VueRouter({
routes: [
{ path: "/", component: Main },
{ path: "/user", component: User },
{
//嵌套路由配置在children数组中
path: "/song", component: Song, children: [
{ path: "/song/tab1", component: Tab1 },
{ path: "/song/tab2", component: Tab2 }
]
}
]
})
var app = new Vue({
el: '#app',
//6.挂载router,
router: router,
})
</script>
当你访问一个地址时你期望他跳转到另一个地址,这是就要用到路由重定向
路由重定向就是在配置VueRouter
对象时多添加加一个路由,让这个路由redirect另一个路由这就跳转了
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
var User = {
template: "User:{{ $route.params.id }}
"
}
routes: [
{ path: "/user/:id", component: User },
{ path: "/song", component: Song }
]
该形式只能接受前端穿过来的参数
该形式除了接受前端穿过来的参数,而且还能接受穿过来的静态对象参数
导航就是页面的地址转换
导航分为:1.声明式导航,2.编程式导航
声明式导航:
主要是依赖在页面中已经声明的a标签
或vue中的router-link
标签进行页面跳转
编程式导航:
主要是在js进行导航的跳转,如:普通js中的location.href
而在vue中编程式导航是利用:
router.push的参数规则
当你访问一个地址时你期望他跳转到另一个地址,这是就要用到路由重定向
路由重定向就是在配置VueRouter
对象时多添加加一个路由,让这个路由redirect另一个路由这就跳转了
[外链图片转存中…(img-gjRoDO4T-1604480025359)]
[外链图片转存中…(img-DpurrlAq-1604480025360)]
<router-link to="/user/1">User1</router-link>
<router-link to="/user/2">User2</router-link>
<router-link to="/user/3">User3</router-link>
var User = {
template: "User:{{ $route.params.id }}
"
}
routes: [
{ path: "/user/:id", component: User },
{ path: "/song", component: Song }
]
该形式只能接受前端穿过来的参数
[外链图片转存中…(img-bG4RxdZk-1604480025361)]
该形式除了接受前端穿过来的参数,而且还能接受穿过来的静态对象参数
[外链图片转存中…(img-ax2CE9DP-1604480025362)]
[外链图片转存中…(img-SN4PWYCc-1604480025363)]
导航就是页面的地址转换
导航分为:1.声明式导航,2.编程式导航
声明式导航:
主要是依赖在页面中已经声明的a标签
或vue中的router-link
标签进行页面跳转
编程式导航:
主要是在js进行导航的跳转,如:普通js中的location.href
而在vue中编程式导航是利用:
router.push的参数规则