Vue.js 的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进 DOM 的系统:
<div id="app">
{{ msg }}
</div>
//实例化代码
var app = new Vue({
el: '#app',
data: {
msg: '欢迎学习Vue'
}
})
{{ msg }} 为什么会变成 msg 的值?vue 使用基本 html 的模板语法,允许开发者声明式地将DOM 绑定至底层 vue 实例的数据,所有 vue 模板都是合法的 html,所以能被遵循规范的浏览器和 html 解析器解析。
2.1、mustache语法
mustache 翻译为中文,是胡子/胡须。由于 {{ msg }} 两边都有对称的大括号,就像人的胡须一样,所以就叫做 mustache 语法。
特点:不仅可以直接写成变量,也可以添加简单的表达式。
//写法多样,使用便捷
<h2> {{ msg }} <h2>
<h2> {{ fir+' '+sed }} <h2>
<h2> {{ fir }} {{sed}} <h2>
<h2> {{ number + 1 }} <h2>
<h2> {{ message.split('').reverse().join('') }} <h2>
2.2、v-once
上边的数据绑定中,页面展示 msg 的值,如果我们在浏览器调试中,修改 msg 的值,页面立马会更新,始终保持最新的值为页面内容。
调试模式,输入如下内容观察:
app.msg="你不爱我了" //回车
vue 支持动态渲染文本,在修改属性的同时,实时渲染文本。为了提高渲染效率,只需第一次渲染出文本之后,后期属性再修改不会影响文本内容。
此时就需要使用 v-once 解决问题。
//使用语法
<span v-once>{{msg}}</span>
特点:该指令后面不需要任何表达式,表示元素或组件只渲染一次,不会随数据的改变而改变文本。
2.3、v-html
在某些特殊情况下,页面需要动态地插入一段 html 代码,比如编辑器,动态传入的就是一段html 代码,使用时我们需要原样输出,如:
<div>{{url}}</div>
data(){
return{
url:'<a href="http://www.baidu.com">百度首页</a>'
}
}
直接这么写并不能满足我们的要求,我们需要展示成带有超链接的百度首页,此时 v-html 登场。
// v-html 使用语法
<div v-html="url"></div>
给元素添加 v-html 指令后,元素就展示成一个带有超链接的百度首页文字。
v-html 特点:可以解析字段内的标签,把内容当作 html 标签来处理。
2.4、v-text
// 使用语法
<span v-text="msg"></span>
特点:与 mustache 语法类似,用于展示文本的。使用没有 mustache 灵活,所以使用较少。
注意点:<span v-text="msg">新内容</text> 标签中又新增内容时,会把原来 msg 中的内容覆盖掉。
2.5、v-pre
v-pre 与 html 中的 pre 标签有些类似,html 中的 pre 会原样输入空格、换行、缩进和文本内容。v-pre 也是原样输出内容,不会解析。
// 使用语法
<div v-pre> {{ msg }} </div>
页面直接输出 {{ msg }}
2.6、v-cloak
cloak 翻译成中文,是斗篷。那么 v-cloak是用来干什么的呢?
html页面运行的时候,会闪现 {{ msg }} ,如图:
v-locak 就是用来解决这个问题的。
// 使用语法
<div v-cloak> {{ msg }} </div>
特点:在 vue 解析之前,元素有 v-cloak 属性,vue 解析之后,元素没有 v-cloak 属性。
利用 v-cloak 的特点,我们在 css 中添加
[v-cloak]{
display:'none'
}
此时再运行网页的时候,解析之前会被隐藏掉,解析之后才展示内容,就不会再闪现 {{msg}}。
话不多说,看图!
本篇文章介绍 Vue3 + vite +TS 项目内使用 Echarts 5 绘制中国地图,标记分布点!之前没有接触过 Echarts 的,可以先去官方示例看看,里面图形特别齐全。但是官方文档看着费劲的,太多了根本记不住,所以自己做个总结,下次就可以直接使用了,不用做重复无用功。
Echarts 已更新到了 5.0 版本,安装完记得检查下自己的版本是否是 5.0 。
npm install echarts --save
安装完成之后,在 package.json 中检查是否安装成功?
可以下载中国以及各个省份地图数据。免费的文件下载地址:
http://datav.aliyun.com/portal/school/atlas/area_selector#&lat=30.332329214580188&lng=106.72278672066881&zoom=3.5
记得收藏哦!免得浪费加班时间。
引入 echarts 可以全局引入:
import * as echarts from "echarts"
/* 之前vue2 */
Vue.prototype.$ecahrt = echarts
/* vue3 */
app.config.globalProperties.$echarts = echarts
也可以直接在绘制页面内按需引用。
引入需要绘制的地图数据 json 或 js 文件,本文使用的是 json 格式:
import chinaJSON from '../../assets/json/china.json'
注意:引入的时候先引入 echarts ,后引入 chinaJSON 文件,顺序不能反哦!
template 部分代码:
<template>
<div>
<div
ref="chinaMap"
style="height: 700px;border: solid 1px red;width: 100%;background: #010111;"
>
地图1
</div>
</div>
</template>
script 部分代码:
<script lang="ts" setup>
import * as echarts from 'echarts'
import chinaJSON from '../../assets/json/china.json'
import { onMounted, ref } from 'vue'
const chinaMap = ref()
onMounted(() => {
drawChina()
})
let regions = [
{
name: '新疆维吾尔自治区',
itemStyle: {
areaColor: '#374ba4',
opacity: 1,
},
},
{
name: '四川省',
itemStyle: {
areaColor: '#fe9b45',
opacity: 1,
},
},
{
name: '陕西省',
itemStyle: {
areaColor: '#fd691b',
opacity: 1,
},
},
{
name: '黑龙江省',
itemStyle: {
areaColor: '#ffc556',
opacity: 1,
},
},
]
let scatter = [
{ name: '北京烤鸭', value: [116.46122, 39.97886, 9] },
{ name: '兰州拉面', value: [103.86615, 36.040129, 9] },
{ name: '新疆烤肉', value: [87.613228, 43.810394, 9] },
{ name: '长沙臭豆腐', value: [112.915204, 28.207735, 9] },
{ name: '西安肉夹馍', value: [108.953445, 34.288842, 9] },
{ name: '云南', value: [102.710002, 25.045806, 9] },
]
function drawChina() {
var myChart = echarts.init(chinaMap.value)
echarts.registerMap('china', chinaJSON) //注册可用的地图
var option = {
geo: {
map: 'china',
roam: true, //是否允许缩放,拖拽
zoom: 1, //初始化大小
//缩放大小限制
scaleLimit: {
min: 1, //最小
max: 2, //最大
},
//设置中心点
center: [115.97, 29.71],
//省份地图添加背景
regions: regions,
itemStyle: {
areaColor: '#0b122e',
color: 'red',
borderColor: '#232652',
borderWidth: 2,
},
//高亮状态
emphasis: {
itemStyle: {
areaColor: '#1af9e5',
color: '#fff',
},
},
},
//配置属性
series: {
type: 'effectScatter',
coordinateSystem: 'geo',
data: scatter,
showEffectOn: 'render',
rippleEffect: {
//涟漪特效相关配置
brushType: 'stroke', //波纹的绘制方式,可选 'stroke' 和 'fill'
},
hoverAnimation: true, //是否开启鼠标 hover 的提示动画效果
label: {
//图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等,
normal: {
formatter: '{b}',
position: 'right',
show: true,
},
},
itemStyle: {
//图形样式,normal 是图形在默认状态下的样式;emphasis 是图形在高亮状态下的样式,比如在鼠标悬浮或者图例联动高亮时
normal: {
color: '#ffffff', //散点的颜色
shadowBlur: 10,
shadowColor: 20,
fontSize: '12px',
},
},
zlevel: 1,
},
}
myChart.setOption(option)
}
</script>
想看更多的可以去官方文档:
https://echarts.apache.org/zh/option.html#geo.regions.emphasis.itemStyle
013年,在Google工作的尤雨溪,开发出了一款轻量Javascript框架,最初命名为Seed,同年12月,更名为Vue,一经推出发展迅速,如今已成为最时髦和炙手可热前端框架,在Github上获得了超过十万的Star,国内许多知名公司都使用Vue作为前端开发工具,例如饿了么、美团等,很多公司的招聘要求都会把会使用vue作为加分项。
Vue的作者 - 尤雨溪
001-Vue的定位是什么?
Vue是一个JavaScript框架,类似的框架有React,Angular等等,所谓框架就是一个比较大型的库,使用它能让基于网页的前端应用程序开发起来更加方便。相对于完全采用原生JavaScript代码来编写前端代码而言,使用框架的代码量更少,开发效率也更高。
需要注意的是,Vue并非UI框架,它的定位与Bootstrap、Frozen UI这一类专注于页面呈现的框架不是一回事,或者说,UI框架关注点在HTML,而Vue这一类框架关注点是JavaScript。Vue可以跟很多UI框架搭配使用,比如说Bootstrap(vueBootstrap),和一些专门与Vue配合的例如饿了吗团队开发的element-ui等等。
002-实现第一个VueJS应用.html
1.下载Vue: https://unpkg.com/vue/dist/vue.js
2.将vue.js拷贝到任意一个目录(工作目录)
3.在同一个目录下用编辑软件(随便什么都行,记事本都可以)新建一个文件,输入以下代码:
<script src="vue.js"></script>
<div id="app">
<p>{{title}}</p>
</div>
<script>
new Vue({
el:"#app",
data:{
title: "Hello World!"
}
});
<script src="vue.js"></script>
<div id="app">
<input type="text" v-on:input="changeTitle">
<p>{{title}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Hello World!"
},
methods: {
changeTitle:function (event) {
this.title = event.target.value;
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<!-- 注意此处并没有调用Vue模板,而是调用了一个函数 -->
<p>{{sayHello()}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Hello World!"
},
methods: {
//此处sayHello是一个方法(函数),但它返回的内容被传送到模版里去了
sayHello:function (event) {
return 'Hello!';
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<p>{{sayHello()}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Hello World!"
},
methods: {
sayHello:function (event) {
//注意此处,return的是Hello World!
//原生的JS是不允许这么调用的,Vue在中间层做了调剂
return this.title;
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<!-- 注意:此处不能用<a href="{{link}}"> 这种形式来传递超链接值,只能用v-bind绑定并设置href的值 -->
<p>{{sayHello()}} - <a v-bind:href="link">Baidu</a> </p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Hello World!",
link:"http://baidu.com"
},
methods: {
sayHello:function () {
return this.title;
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<!-- 注意此处的v-once -->
<h1 v-once>{{title}}</h1>
<p>{{sayHello()}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Hello World!",
},
methods: {
sayHello:function () {
this.title = 'Hello';
return this.title;
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<!-- 注意此处的v-once -->
<h1 v-once>{{title}}</h1>
<p>{{sayHello()}}</p>
<!-- 注意:v-html指令让finishedLink以渲染后的HTML格式输出,而不是纯文本
如果以花括号{{finishedLink}} 来表示的话,将会是一个HTML形式的纯文本。
-->
<p v-html = "finishedLink" ></p>
</div>
<script>
new Vue({
el: "#app",
data: {
title: "Hello World!",
finishedLink:'<a href="http://baidu.com">Baidu.com</a>',
},
methods: {
sayHello:function () {
this.title = 'Hello';
return this.title;
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<p>I am {{name}}</h1>
<p>I am {{age}} years old.</p>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "Rockage",
age: "40",
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<p>I am {{name}}</p>
<p>I am {{age * 3}} years old.</p>
</div>
<script>
new Vue({
el: "#app",
data: {
name: "Rockage",
age: "40",
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<p>The Random Number is : {{sayRnd()}}</p>
</div>
<script>
new Vue({
el: "#app",
methods: {
sayRnd: function () {
// random_number = Math.random(); // 产生一个0到1的随机数
// random_number = random_number.toFixed(2) //保留两位小数
// 产生一个1到100的随机数
random_number = Math.floor(Math.random() * (100 - 1 + 1)) + 1
return random_number;
}
}
});
</script>
<script src="vue.js" xmlns:v-bind="http://www.w3.org/1999/xhtml"></script>
<div id="app">
<img v-bind:src = "url">
</div>
<script>
new Vue({
el: "#app",
data: {
url: "http://img.mp.itc.cn/upload/20170217/1f650c2645c541ad8cc70842d7d0bbe5_th.jpeg"
}
});
</script>
<script src="vue.js" xmlns:v-bind="http://www.w3.org/1999/xhtml"></script>
<div id="app">
Name <input type = "text" v-bind:value = "default_name" />
</div>
<script>
new Vue({
el: "#app",
data: {
default_name: "Hua Yang"
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<button v-on:click="increase">Click Me</button>
<p>{{ counter}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
increase: function () {
this.counter++;
}
},
});
</script>
<script src="vue.js"></script>
<div id="app">
<p v-on:mousemove="updateCoordinates">Coordonates : {{x}}/{{y}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
updateCoordinates: function (event) {
this.x = event.clientX;
this.y = event.clientY;
}
},
});
</script>
<script src="vue.js"></script>
<div id="app">
<!--
请注意, 调用increase时增加了两个参数
-->
<button v-on:click="increase(2,$event)">Click Me</button>
<p>{{ counter}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
// increase 函数用step和event接收参数
increase: function (step,event) {
this.counter += step;
}
},
});
</script>
HTML部分:
<span v-on:mousemove = "dummy">DEAD SPOT</span>
JS部分:
dummy: function(){
event.stopPropagation();
}
以上代码确保事件不会传播给绑定有这个属性的SPAN上,当然,我们还有更简单的方法,就是使用事件修饰符,使用stop修饰符即可实现这个目的:
<script src="vue.js"></script>
<div id="app">
<p v-on:mousemove="updateCoordinates">Coordonates : {{x}}/{{y}}
<!-- 请注意下面这个SPAN绑定的事件mousemove
采用了.stop修饰符,表示此元素的mousemove事件不做任何处理
-->
- <span v-on:mousemove.stop = "">DEAD SPOT</span>
</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
updateCoordinates: function (event) {
this.x = event.clientX;
this.y = event.clientY;
}
},
});
</script>
<script src="vue.js"></script>
<div id="app">
<input type = "text" v-on:keyup.enter="alertMe" />
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
alertMe: function () {
alert("Alert!");
}
},
});
</script>
<script src="vue.js"></script>
<div id="app">
<button v-on:click="alertMe">Show Alert</button>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0,
x: 0,
y: 0
},
methods: {
alertMe: function () {
alert("You Clicked me!");
}
},
});
</script>
<script src="vue.js"></script>
<div id="app">
<input v-on:keydown = "myValue = $event.target.value" type="text"/>
<p>{{myValue}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
myValue: ''
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<input v-on:keydown.enter = "myValue = $event.target.value" type="text"/>
<p>{{myValue}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
myValue: ''
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<!-- 此处取消了事件函数,直接用counter++代替 -->
<button v-on:click="counter++">Click Me</button>
<!-- 此处直接修改模板counter的值 -->
<p>{{ counter * 2}}</p>
<!-- 此处是一个三元表达式,用以判断counter的值 -->
<p>{{ counter * 2 > 10 ? 'Greate than 10' : 'Smaller than 10'}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter: 0
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<input type = "text" v-model = "name">
<p>{{name}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
name: ''
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<button v-on:click="counter1++">Increase Counter 1</button>
<button v-on:click="counter1--">Decrease Counter 1</button>
<button v-on:click="counter2++">Increase Counter 2</button>
<p>Counter:{{counter1}} | {{counter2}}</p>
<!-- 注意两种调用方法是不同的 -->
<p>Counter 1 Result: {{result()}} | {{output}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
counter1: 0,
counter2: 0
},
computed: {
output: function () {
console.log('Here is Computed')
return this.counter1 > 5 ? "Greater than 5" : "Smaller than 5"
}
},
methods: {
result: function () {
console.log('Here is Methods')
return this.counter1 > 5 ? "Greater than 5" : "Smaller than 5"
}
}
});
</script>
<!-- 作业3问题:响应式属性 - 作业1 -->
<script src="vue.js"></script>
<div id="app">
<button v-on:click="value += 5">Add 5</button>
<button v-on:click="value += 1">Add 1</button>
<p>{{result}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
value: 0,
},
computed: {
result: function () {
return this.value == 37 ? "Done" : "Not there yet"
}
}
});
</script>
<script src="vue.js"></script>
<div id="app">
<button v-on:click="value += 5">Add 5</button>
<button v-on:click="value += 1">Add 1</button>
<p>Current Value:{{value}} </p>
<p>{{result}}</p>
</div>
<script>
new Vue({
el: "#app",
data: {
value: 0
},
computed: {
result: function () {
return this.value == 37 ? "Done" : "Not there yet"
}
},
watch: {
result: function () { //watch可以监听computed里的属性
var vm = this;
setTimeout(function () {
vm.value = 0
// 但无法修改computed里定义的属性,即如果写成 vm.result = "XXX" 则程序会报错
}, 5000)
}
}
});
</script>
<style>
.demo {
width: 100px;
height: 100px;
background-color: gray;
display: inline-block;
margin: 10px;
}
.red {
background-color: red;
}
}
</style>
<script src="vue.js"></script>
<div id="app">
<div
class="demo"
@click="attachRed = !attachRed"
:class="{red: attachRed}"
></div>
</div>
<script>
new Vue({
el: "#app",
data: {
attachRed: false
}
});
</script>
<style>
.demo {
width: 100px;
height: 100px;
background-color: gray;
display: inline-block;
margin: 10px;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
</style>
<script src="vue.js"></script>
<div id="app">
<div
class="demo"
@click="attachRed = !attachRed"
:class="divClasses"
></div>
</div>
<script>
new Vue({
el: "#app",
data: {
attachRed: false
},
computed: {
divClasses: function () {
return {
red: this.attachRed,
blue: !this.attachRed
}
}
}
});
</script>
<!-- 033-CSS类动态样式-使用命名 -->
<style>
.demo {
width: 100px;
height: 100px;
background-color: gray;
display: inline-block;
margin: 10px;
}
.red {
background-color: red;
}
.blue {
background-color: blue;
}
.green {
background-color: green;
}
</style>
<script src="vue.js"></script>
<div id="app">
<div
class="demo"
@click="attachRed = !attachRed"
:class="divClasses"
></div>
<div
class="demo"
:class="[color,{red: attachRed}]"
></div>
<hr>
<!-- 此处输入框双向绑定了color属性,即键盘输入的内容会即时作为CSS类名传到HTML中去 -->
<input type = "text" v-model = "color">
</div>
<script>
new Vue({
el: "#app",
data: {
attachRed: false,
color:'green'
//color属性默认为green,请注意由于双向绑定的原因,green这个字符串也会同时传递到输入框里
},
computed: {
divClasses: function () {
return {
red: this.attachRed,
blue: !this.attachRed
}
}
}
});
</script>
<div class="demo" :style="{'background-color':color}"></div>
data: { color: 'grey', width: 100}
<input type="text" v-model="color">
<!-- 章节2课时34-动态设置样式(不使用CSS类) -->
<style>
.demo {
width: 100px;
height: 100px;
background-color: gray;
display: inline-block;
margin: 10px;
}
</style>
<script src="vue.js"></script>
<div id="app">
<div class="demo" :style="{'background-color':color}"></div>
<div class="demo" :style="myStyle"></div>
<hr>
<input type="text" v-model="color">
<input type="text" v-model="width">
</div>
<script>
new Vue({
el: "#app",
data: {
color: 'grey',
width: 100
},
computed: {
myStyle: function () {
return {
backgroundColor: this.color,
width: this.width + 'px'
}
}
}
});
</script>
*请认真填写需求信息,我们会在24小时内与您取得联系。