我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛
夏日天气多变,一会雨,一会大太阳。今天,咱们就来尝试自己做一个天气显示页面吧
用 Vue ?React ?
不不不
用 Svelte !
Svelte ! 是一种全新的构建用户界面的方法。传统框架如 React 和 Vue 在浏览器中需要做大量的工作,而 Svelte 将这些工作放到构建应用程序的编译阶段来处理。
与使用虚拟(virtual)DOM 差异对比不同。Svelte 编写的代码在应用程序的状态更改时就能像做外科手术一样更新 DOM。
构建项目
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev
svelte 的官网贴心的为我们准备了基础教程。
相信看这个文章的小伙伴,应该都是学习过 Vue 或者 React 框架的,对于变量的绑定,事件的定义和绑定都比较清楚。这里我们不会特别仔细的讲解。
<script>
let string = `this string contains some <strong>HTML!!!</strong>`;
// 代码逻辑部分
</script>
// 页面部分
<p>{string}</p>
// 样式部分
<style>
</style>
是不是和 Vue 一模一样
上面输入城市名称,敲击回车,请求数据。数据返回,显示在页面上。
<script>
let value = "";
async function handleChange() {
// 请求数据
}
</script>
<input type="text" on:change={handleChange} bind:value />
这里请求数据,我们使用
这个接口
cityCode 为城市编码
appid 和 appsecret 登录账号之后,即可获得。
这里我实现的方式比较简单。通过数组的方式,返回需要的数据,即将该数据改造为
获取用户输入的城市名称之后,通过数组的 find 方法,返回 code,之后调用请求接口。
<script>
import { onMount } from "svelte";
import { cityCodeArr } from "./utils/cityCode";
let cityName = "";
let showDate = "";
let currentTem = "";
let heightTem1 = "";
let lowTem2 = "";
let weather = "";
let value = "";
let cityArr = [];
let cityCode = "";
onMount(async () => {
cityArr = cityCodeArr.map((item) => {
return {
cityName: item[2],
code: item[0],
};
});
init();
});
async function handleChange() {
const code = cityArr.find((item) => item.cityName === value).code;
cityCode = code;
init();
}
async function init() {
const endpoint = `https://www.tianqiapi.com/api?version=v6&appid=59736232&appsecret=cU5UZ65u&cityid=${cityCode}`;
const response = await fetch(endpoint);
const { city, date, tem, tem1, tem2, wea } = await response.json();
cityName = city;
weather = wea;
heightTem1 = tem1;
lowTem2 = tem2;
currentTem = tem;
showDate = date;
}
</script>
通过不同的 weather 值,渲染不同的天气卡片。
<main>
<div class="content">
<input type="text" on:change={handleChange} bind:value />
{#if weather === "晴"}
<Sunny />
{:else if weather === "多云"}
<Cloudy />
{:else if weather === "阴"}
<Overcast />
{:else if weather.includes("雨")}
<Rainy />
{:else if weather.includes("雪")}
<Snowy />
{/if}
<div />
<div>当前城市:{cityName}</div>
<div>当前日期:{showDate}</div>
<div>当前气温:{currentTem}</div>
<div class="">最高气温:{heightTem1}</div>
<div class="">最低气温:{lowTem2}</div>
</div>
</main>
外边框
<style>
.weather {
position: relative;
display: inline-block;
width: 180px;
height: 240px;
background: #23b7e5;
border-radius: 8px;
margin-left: 20px;
}
</style>
太阳🌞
<style>
.sunny::before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: #f6d963;
border-radius: 50%;
box-shadow: 0 0 20px #ff0;
z-index: 2;
}
.sunny::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
margin: -45px 0 0 -45px;
width: 90px;
height: 90px;
background: #ffeb3b;
clip-path: polygon(
50% 0%,
64.43% 25%,
93.3% 25%,
78.87% 50%,
93.3% 75%,
64.43% 75%,
50% 100%,
35.57% 75%,
6.7% 75%,
21.13% 50%,
6.7% 25%,
35.57% 25%
);
z-index: 1;
animation: sunScale 2s linear infinite;
}
@keyframes sunScale {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
</style>
云☁️
<style>
.overcast::before {
content: "";
position: absolute;
top: 50%;
left: 25%;
transform: translate(-50%, -50%);
width: 36px;
height: 36px;
background: #fff;
border-radius: 50%;
box-shadow: #fff 22px -15px 0 6px, #fff 57px -6px 0 2px,
#fff 87px 4px 0 -4px, #fff 33px 6px 0 6px, #fff 61px 6px 0 2px,
#ccc 29px -23px 0 6px, #ccc 64px -14px 0 2px, #ccc 94px -4px 0 -4px;
z-index: 2;
animation: cloudMove 2s linear infinite;
}
@keyframes cloudMove {
0% {
transform: translate(-50%, -50%);
}
50% {
transform: translate(-50%, -60%);
}
100% {
transform: translate(-50%, -50%);
}
}
</style>
雨🌧️
<style>
.rainy::before {
content: "";
position: absolute;
top: 50%;
left: 25%;
transform: translate(-50%, -50%);
width: 36px;
height: 36px;
background: #fff;
border-radius: 50%;
box-shadow: #fff 22px -15px 0 6px, #fff 57px -6px 0 2px,
#fff 87px 4px 0 -4px, #fff 33px 6px 0 6px, #fff 61px 6px 0 2px,
#ccc 29px -23px 0 6px, #ccc 64px -14px 0 2px, #ccc 94px -4px 0 -4px;
z-index: 2;
}
.rainy::after {
content: "";
position: absolute;
top: 50%;
left: 25%;
width: 4px;
height: 14px;
background: #fff;
border-radius: 2px;
box-shadow: #fff 25px -10px 0, #fff 50px 0 0, #fff 75px -10px 0,
#fff 0 25px 0, #fff 25px 15px 0, #fff 50px 25px 0, #fff 75px 15px 0,
#fff 0 50px 0, #fff 25px 40px 0, #fff 50px 50px 0, #fff 75px 40px 0;
animation: rainDrop 2s linear infinite;
}
@keyframes rainDrop {
0% {
transform: translate(0, 0) rotate(10deg);
}
100% {
transform: translate(-4px, 24px) rotate(10deg);
box-shadow: #fff 25px -10px 0, #fff 50px 0 0, #fff 75px -10px 0,
#fff 0 25px 0, #fff 25px 15px 0, #fff 50px 25px 0, #fff 75px 15px 0,
rgba(255, 255, 255, 0) 0 50px 0, rgba(255, 255, 255, 0) 25px 40px 0,
rgba(255, 255, 255, 0) 50px 50px 0, rgba(255, 255, 255, 0) 75px 40px 0;
}
}
</style>
雪❄️
<style>
.snowy::before {
content: "";
position: absolute;
top: 50%;
left: 25%;
transform: translate(-50%, -50%);
width: 36px;
height: 36px;
background: #fff;
border-radius: 50%;
box-shadow: #fff 22px -15px 0 6px, #fff 57px -6px 0 2px,
#fff 87px 4px 0 -4px, #fff 33px 6px 0 6px, #fff 61px 6px 0 2px,
#ccc 29px -23px 0 6px, #ccc 64px -14px 0 2px, #ccc 94px -4px 0 -4px;
z-index: 2;
}
.snowy::after {
content: "";
position: absolute;
top: 50%;
left: 25%;
width: 8px;
height: 8px;
background: #fff;
border-radius: 50%;
box-shadow: #fff 25px -10px 0, #fff 50px 0 0, #fff 75px -10px 0,
#fff 0 25px 0, #fff 25px 15px 0, #fff 50px 25px 0, #fff 75px 15px 0,
#fff 0 50px 0, #fff 25px 40px 0, #fff 50px 50px 0, #fff 75px 40px 0;
animation: snowDrop 2s linear infinite;
}
@keyframes snowDrop {
0% {
transform: translateY(0);
}
100% {
transform: translateY(25px);
box-shadow: #fff 25px -10px 0, #fff 50px 0 0, #fff 75px -10px 0,
#fff 0 25px 0, #fff 25px 15px 0, #fff 50px 25px 0, #fff 75px 15px 0,
rgba(255, 255, 255, 0) 0 50px 0, rgba(255, 255, 255, 0) 25px 40px 0,
rgba(255, 255, 255, 0) 50px 50px 0, rgba(255, 255, 255, 0) 75px 40px 0;
}
}
</style>
多云
<style>
.weather {
position: relative;
display: inline-block;
width: 180px;
height: 240px;
background: #23b7e5;
border-radius: 8px;
margin-left: 20px;
}
.sunny:before {
content: "";
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 60px;
height: 60px;
background: #f6d963;
border-radius: 50%;
box-shadow: 0 0 20px #ff0;
z-index: 2;
}
.sunny:after {
content: "";
position: absolute;
top: 50%;
left: 50%;
margin: -45px 0 0 -45px;
width: 90px;
height: 90px;
background: #ffeb3b;
clip-path: polygon(
50% 0%,
64.43% 25%,
93.3% 25%,
78.87% 50%,
93.3% 75%,
64.43% 75%,
50% 100%,
35.57% 75%,
6.7% 75%,
21.13% 50%,
6.7% 25%,
35.57% 25%
);
z-index: 1;
animation: sunScale 2s linear infinite;
}
@keyframes sunScale {
0% {
transform: scale(1);
}
50% {
transform: scale(1.1);
}
100% {
transform: scale(1);
}
}
.cloudy::before {
content: "";
position: absolute;
top: 50%;
left: 25%;
transform: translate(-50%, -50%);
width: 36px;
height: 36px;
background: #fff;
border-radius: 50%;
box-shadow: #fff 22px -15px 0 6px, #fff 57px -6px 0 2px,
#fff 87px 4px 0 -4px, #fff 33px 6px 0 6px, #fff 61px 6px 0 2px,
#ccc 29px -23px 0 6px, #ccc 64px -14px 0 2px, #ccc 94px -4px 0 -4px;
z-index: 2;
animation: cloudMove 2s linear infinite;
}
@keyframes cloudMove {
0% {
transform: translate(-50%, -50%);
}
50% {
transform: translate(-50%, -60%);
}
100% {
transform: translate(-50%, -50%);
}
}
</style>
导入页面中
<script>
import Sunny from "./components/Sunny.svelte";
import Cloudy from "./components/Cloudy.svelte";
import Overcast from "./components/Overcast.svelte";
import Rainy from "./components/Rainy.svelte";
import Snowy from "./components/Snowy.svelte";
</script>
总体来说,语法其实相差不大。如果是学过框架的小伙伴,其实还是很容易上手的。
尝鲜就这么多啦,剩下的,多多参考官网