- 为啥现在对后端要求这么高?
- 为啥不要求前端会后端呢?
可能是后端人太多了,要求后端需要会前端的框架(vue react angular ),
这不我为了适应市场的需求来系统的学习vue了:
生成一个基础的vue项目
创建vue项目
vue create projectname
如果是vue2的话,那么可以使用 `vue init webpack '来创建vue2的项目
创建vite+vue
npm init vite@latest projectname --template vue
package.json
记录项目信息,名称,版本
生产依赖以及开发依赖
package-lock.json
追踪package.json中的依赖版本
项目结构:
node_modules 依赖文件夹
public 资源文件夹
src 源码文件夹
package.json 信息描述文件
vite.config.js vue配置文件
package-lock.json 依赖确定文件
模板语法:
App.vue
<script>
export default{
data(){
// 每个绑定仅支持单一表达式,也就是能够被求值的js代码
return {
msg:"模板语法",
key:"键值对",
ok:true,
net:"<a href='http://www.baidu.com'>百度一下</a>"
}
}
}
</script>
<!-- 模板语法 -->
<template>
<h1>vue基础--文本插值</h1>
<p>{{ msg.split("").reverse().join("") }}</p>
<span>{{ key }}</span>
<p>{{ ok?'yes':'no' }}</p>
<p>{{ net }}</p>
<!-- 使用原始html 需要使用 v-html -->
<p v-html="net"></p>
</template>
双大括号将会将数据插值解析为文本,而不是html,若想插入html,需要使用v-html
属性绑定
<script>
export default{
data(){
// 每个绑定仅支持单一表达式,也就是能够被求值的js代码
return {
msg:"模板语法",
key:"键值对",
ok:true,
net:"<a href='http://www.baidu.com'>百度一下</a>",
dynamicId: "appid",
dynamicClass:"appclass",
name:"中国"
}
}
}
</script>
<!-- 模板语法 -->
<template>
<h1>vue基础--文本插值</h1>
<p>{{ msg.split("").reverse().join("") }}</p>
<span>{{ key }}</span>
<p>{{ ok?'yes':'no' }}</p>
<p>{{ net }}</p>
<!-- 使用原始html 需要使用 v-html -->
<p v-html="net"></p>
<!-- 绑定属性使用 v-bind-->
<div v-bind:id="dynamicId" v-bind:class="dynamicClass">{{ name }}</div>
</template>
由于属性绑定很常用,所以可以简写为 :
所以上面属性绑定多个部分可以是下面这个样子的:
<div :id="dynamicId" :class="dynamicClass">{{ appName }}</div>
事件处理
内联事件处理与方法事件处理
<template>
<div>
<!-- 内联事件处理器-->
<button @click="countNum++">加一</button>
<p>Count is :{{countNum}}</p>
<!-- 方法事件处理器-->
<button @click="addNum">加2</button>
<p>{{countNum2}}</p>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
modifyFlag: true,
countNum: 0,
countNum2: 0,
}
},
methods: {
addNum() {
this.countNum2 += 2
}
}
}
</script>
<style scoped>
</style>
参数传递
<template>
<div>
<div>
<button @click="getEvent">获得一个事件</button>
</div>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
modifyFlag: true,
countNum: 0,
countNum2: 0,
}
},
methods: {
getEvent(e){
console.log(e)
alert(e)
this.countNum += 1;
}
}
}
</script>
<style scoped>
</style>
参数传递:
比如下面这样,当点击某一行时,可以获取该行的某项数据,这样就可以传给后端相应的数据;
<template>
<div>
<!--事件传参-->
<div>
<p @click="getNameList(item)" v-for="item in nameList">{{item}}</p>
</div>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
nameList:['张三','李四','王五']
}
},
methods: {
getNameList(name){
alert(name)
}
}
}
</script>
前端显示:
我们点击姓名时会弹出窗显示姓名:
如果我们既想传递数据也想传递事件,此时方法中的顺序~先参数后事件
getEvent(num,$enent)
了解到这里之后,我们就能理解 一些框架 比如elementUI可以直接拿到参数:
下面是一个elementUI的表单组件,表当绑定了一个list 即nameList,通过请求后端获得一个list之后只需在列上绑定属性即可在表单中填充相应的值~省去了我们主动去遍历显示;
<el-table :data="nameList" class="w-full">
<el-table-column label="编号" align="center" prop="id" :show-overflow-tooltip="true">
</el-table-column>
<el-table-column label="姓名" align="center" prop="name" :show-overflow-tooltip="true"/>
<el-table-column label="性别" align="center" prop="sex" :show-overflow-tooltip="true" key="slot">
<template slot-scope="scope">
<span v-if="scope.row.sex==0">男</span>
<span v-if="scope.row.sex==1">女</span>
</template>
</el-table-column>
</el-table>
....数据项....
<script>
export default {
name: "goodsTest",
data() {
return {
nameList: [
{
id: 1,
name: '张三',
sex:0
}, {
id: 2,
name: '李四',
sex:1
},
]
}
},
methods: {
}
}
</script>
展示效果如下:
事件修饰
下面一个链接,点击后跳转到百度
<template>
<div>
<a @click="clickHandle" href="https://www.baidu.com">百度一下</a>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
},
methods: {
clickHandle(e) {
// 阻止事件
e.preventDefault()
}
}
}
</script>
正常情况下我们点击会跳转,但是我们可以阻止事件的发生~才方法中调用方法阻止事件发生
我们也可以直接采用下面的方式
<template>
<div>
<a @click.prevent="clickHandle" href="https://www.baidu.com">百度一下</a>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
},
methods: {
clickHandle(e) {
// 阻止事件
//e.preventDefault()
}
}
}
</script>
事件穿透
事件穿透简单来说就是触发子元素的事件的同时父元素的事件也被触发了,比如下面这种情况:
<template>
<div>
<div @click="clickDIV">
<p @click="clickP">
点击P
</p>
</div>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
}
},
methods: {
clickDIV(){
console.log("触发了点击DIV")
},
clickP(){
console.log("点击P触发了")
},
}
}
</script>
我们现在不想触发div的事件,那么可以在方法中传递事件e然后通过e调用stopPropagation方法来实现;
methods: {
clickDIV(e){
console.log("触发了点击DIV")
},
clickP(e){
console.log("点击P触发了")
e.stopPropagation()
},
或者像下面这样:
<div @click="clickDIV">
<p @click.stop="clickP">
点击P
</p>
</div>
监听数组变更
VUE可以监听响应式数组的变更方法,并在他们被调用时触发更新,这些方法包括:
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
不触发更新的方法如下:
filter()
concat()
slice()
这里需要重新赋值一下才能触发更新效果
来吧,展示:
<template>
<el-button @click="addName">增加</el-button>
<el-table :data="nameList" class="w-full">
<el-table-column label="编号" align="center" prop="id" :show-overflow-tooltip="true">
</el-table-column>
<el-table-column label="姓名" align="center" prop="name" :show-overflow-tooltip="true"/>
<el-table-column label="性别" align="center" prop="sex" :show-overflow-tooltip="true" key="slot">
<template slot-scope="scope">
<span v-if="scope.row.sex==0">男</span>
<span v-if="scope.row.sex==1">女</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
nameList: [
{
id: 1,
name: '张三',
sex: 0
}, {
id: 2,
name: '李四',
sex: 1
},
]
}
},
methods: {
addName() {
let nameData = {id: 3, name: '王五', sex: 1};
this.nameList.push(nameData)
}
}
}
</script>
点击增加按钮后,表单数据会自动更新
试一下其他方法:
addName() {
const nameData = {id: 3, name: '王五', sex: 1};
// this.nameList.push(nameData)
this.nameList.concat(nameData) //UI不会更新
this.nameList=this.nameList.concat(nameData)//此时UI才会更新
},
计算属性
为什么说是计算属性呢?
看下面的例子:
<template>
<div>
<p>{{viewTrueOrFalse}}</p>
</div>
</template>
<script>
export default {
name: "goodsTest",
data() {
return {
modifyFlag: true
}
},
//计算属性
computed: {
viewTrueOrFalse() {
return this.modifyFlag == true ? 'YES' : 'NO'
}
},
methods: {
getNameList(name) {
alert(name)
}
}
}
</script>
<style scoped>
</style>
上面通过方法也可以实现:
再增加一个P标签
<p>{{viewTrueOrFalse2()}}</p>
再增加一个方法:
viewTrueOrFalse2(){ return this.modifyFlag == true ? 'YES' : 'NO' },
效果如下:
计算属性跟方法的区别:
~计算属性关键字:computed
计算属性的值会基于其响应式依赖被缓存,即一个计算属性仅会在其响应式依赖被更新时才会重新计算;
方法在调用时总会重新调用计算;
就比如我们复制多个计算属性的
<p>{{viewTrueOrFalse}}</p>
此时会因为缓存而直接使用缓存的值(只计算一次)
如果复制多个<p>{{viewTrueOrFalse2()}}</p>
则每一个会重新计算后重新渲染(计算4次)