随意切换React和Vue, 你说有没有搞头?
第一篇: 只做环境跟首页的处理
先上效果图
一、Vue3的环境搭建
-
vue create vue3-demo之后
-
按需选择
-
回车之后选3.x版本的vue
-
把babel,postcss,eslint这些配置文件放哪? 选择放在独立文件夹
-
完成Vue3的坏境搭建
二、Vant3的环境搭建
-
npm i vant@next -S
-
按需引入 npm i babel-plugin-import -D
-
对于使用 babel7 的用户,可以在 babel.config.js 中配置。地址:根文件夹/babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant'],
['@vue/babel-plugin-jsx'] // jsx的扩展待会会用到
]
};
- 对main.js的改造。方法之一,有更好的方法。 位置:src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { Button, Icon, NavBar, Swipe, SwipeItem, List } from 'vant';
const app = createApp(App);
app.use(Swipe);
app.use(SwipeItem);
app.use(NavBar);
app.use(Button);
app.use(store).use(router).mount('#app');
- 完成vant的环境搭建
三、JSX的环境搭建
-
yarn add -D @vue/babel-plugin-jsx 或者 npm install @vue/babel-plugin-jsx -D
-
位置: 根目录/babel.config.js配置
// 之前我们上面的代码
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
['import', {
libraryName: 'vant',
libraryDirectory: 'es',
style: true
}, 'vant'],
['@vue/babel-plugin-jsx']
]
};
- 完成jsx的配置。可以使用jsx了
四、完成首页
第一步: 对App.vue的进行改造
位置: src/App.vue 改成 App.jsx来测试jsx环境是否成功
// App.jsx
const App = ({
render(){
return <router-view/>
}
});
export default App
第二步: 新建view/home/index.jsx
// view/home/index.jsx
import { reactive } from 'vue'
import './index.scss'
// mock数据tabBar
const tabBarMock = [
{
id: 0,
title: '推荐',
path: '/recommend'
},
{
id: 1,
title: '歌手',
path: '/singer'
},
{
id: 2,
title: '排行',
},
];
const Home = ({
name: 'Home',
setup(props) {
const state = reactive({
list: [],
tabBarIndex: 0
});
// 导航栏搜索
const handleNavSearch = () => {
console.log('搜索');
};
// 导航栏展开
const handleNavExtend = () => {
console.log('展开');
};
// tabBar切换
const handleTabClick = (id) => {
state.tabBarIndex = id;
};
const renderNavRight = <van-icon name="search" size="18" color="#fff" onClick={handleNavSearch}/>;
const renderNavLeft = <van-icon name="wap-nav" size="18" color="#fff" onClick={handleNavExtend}/>;
const renderTabBar = () => {
return (
<div className="tabBar">
{
tabBarMock.map(item => {
return (
<div key={item.id} onClick={() => handleTabClick(item.id)}>
<span className={state.tabBarIndex === item.id ? 'tabBarIndex' : ''}>
{item.title}
</span>
</div>
)
})
}
</div>
)
};
// 最终的渲染
return () => (
<div className="viewBox">
<van-nav-bar
title="Pro"
v-slots={{
'right': () => renderNavRight,
'left': () => renderNavLeft
}}
/>
{
renderTabBar()
}
<div className="wrapBox">
<router-view/>
</div>
</div>
)
},
});
export default Home
第三步: 新建view/home/index.scss
// view/home/index.scss
// 公共变量
$bgMain: #d44439;
$fontColor: #f1f1f1;
.tabBar{
display: flex;
justify-content: space-between;
text-align: center;
line-height: 40px;
background: $bgMain;
color: $fontColor;
font-size: 14px;
div{
align-items: center;
flex: 1;
}
span{
border-bottom: 2px solid transparent;
padding: 3px 0;
font-weight: 700;
}
.tabBarIndex{
border-bottom: 2px solid #ffffff;
padding: 3px 0;
}
}
.van-nav-bar{
background-color: $bgMain;
div{
color: $fontColor;
}
}
.van-nav-bar::after{
border-bottom: none;
}
到此、我们的Home模块算完成了。接下来完成他的子路由。通过tabBar来切换路径
看效果图
第四步: 改装router、位置:src/router/index.js
// src/router/index.js
import { createRouter, createWebHashHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/home/index'),
children: [
{
path: '/recommend',
name: 'recommend',
component: () => import('../views/recommend/index')
},
],
},
];
const router = createRouter({
history: createWebHashHistory(),
routes
});
export default router
在完成推荐页面之前
我们需要在home/index.jsx补上路由视图跟对路由的监听、后续增加tabBar跳转页面
// home/index.jsx
import { onBeforeMount, reactive } from 'vue';
// 增加路由
import router from '../../router/index';
import './index.scss'
// mock数据tabBar
const tabBarMock = [
{
id: 0,
title: '推荐',
path: '/recommend'
},
{
id: 1,
title: '歌手',
path: '/singer'
},
{
id: 2,
title: '排行',
},
];
const Home = ({
name: 'Home',
setup(props) {
const state = reactive({
list: [],
tabBarIndex: 0
});
// tabBar跳页面
const handleWhichPath = () => {
switch (state.tabBarIndex) {
case 0:
router.push('/recommend');
break;
default:
break;
}
};
// 导航栏搜索
const handleNavSearch = () => {
console.log('搜索');
};
// 导航栏展开
const handleNavExtend = () => {
console.log('展开');
};
// tabBar切换
const handleTabClick = (id) => {
state.tabBarIndex = id;
};
// 增加tabBar判断
onBeforeMount(() => {
handleWhichPath();
});
// navBar的左插槽
const renderNavRight = <van-icon name="search" size="18" color="#fff" onClick={handleNavSearch}/>;
// navBar的右插槽
const renderNavLeft = <van-icon name="wap-nav" size="18" color="#fff" onClick={handleNavExtend}/>;
const renderTabBar = () => {
return (
<div className="tabBar">
{
tabBarMock.map(item => {
return (
<div key={item.id} onClick={() => handleTabClick(item.id)}>
<span className={state.tabBarIndex === item.id ? 'tabBarIndex' : ''}>
{item.title}
</span>
</div>
)
})
}
</div>
)
};
// 渲染
return () => (
<div className="viewBox">
<van-nav-bar
title="Pro"
v-slots={{
'right': () => renderNavRight,
'left': () => renderNavLeft
}}
/>
{
renderTabBar()
}
<div className="wrapBox">
<router-view/>
</div>
</div>
)
},
});
export default Home
第五步: 新建src/view/recommend/index.jsx
import './index.scss';
// 轮播图mock数据
const swipeMock = [
{
id: 0,
picUrl: 'http://p1.music.126.net/L2vC5tVzEGVehAtcjpZ1FQ==/109951165605310291.jpg',
},
{
id: 1,
picUrl: 'http://p1.music.126.net/8vLSxjkhuwpgDPErxyVt4w==/109951165609474509.jpg',
}
];
// listMock数据
const listMock = [
{
id: 5344775532,
type: 0,
name: "复古系|光怪陆离的幻想之旅",
copywriter: "编辑推荐:簇拥着的斑斓色彩↵些许蒙上了年代感的色泽",
picUrl: "https://p2.music.126.net/NoURvJXsYoXrl1HqSoNy3Q==/109951165485850861.jpg",
},
{
id: 5445073692,
type: 0,
name: "醉听曲中事,何妨忆前尘",
copywriter: "编辑推荐: 一曲新词酒一杯,去年天气旧亭台",
picUrl: "https://p2.music.126.net/G-qDlNXkDzutU-aqaKeAfg==/109951165606205375.jpg",
},
{
id: 2857550594,
type: 0,
name: "精选|评论10w+单曲循环歌曲",
copywriter: "热门推荐",
picUrl: "https://p2.music.126.net/UuKmzOfFymLTGW77VTAFMw==/109951164170448016.jpg",
},
{
id: 5312159651,
type: 0,
name: "请 用 动 物 的 本 能 缠 绕 住 我",
copywriter: "热门推荐",
picUrl: "https://p2.music.126.net/5udP0vh4pSTVYTDVOWU7HA==/109951165426321817.jpg",
},
{
id: 3124642208,
type: 0,
name: "网易云评论最多的粤语歌TOP50",
copywriter: "热门推荐",
picUrl: "https://p2.music.126.net/-6osWky_WObfAydYYiTvpA==/3236962232773608.jpg",
},
{
id: 3228441619,
type: 0,
name: "『那些心动的弹唱』钢琴and吉他",
copywriter: "热门推荐",
picUrl: "https://p2.music.126.net/ShJ7Kgh0lvGAUE83LTKzQg==/109951165121506557.jpg",
},
{
id: 4932781493,
type: 0,
name: "“人多 太吵 我突然就不想笑了.”",
copywriter: "热门推荐",
picUrl: "https://p2.music.126.net/0MzdxTmiY0tO4SR4dp6WvA==/109951164845157020.jpg",
},
{
id: 2557744972,
type: 0,
name: "先上DJ先上DJ【土到极致就是嗨】",
copywriter: "热门推荐",
picUrl: "https://p2.music.126.net/AzQ5PYt2VYAIUM-506fHoQ==/109951165502267501.jpg",
},
{
id: 5344775532,
type: 0,
name: "复古系|光怪陆离的幻想之旅",
copywriter: "编辑推荐:簇拥着的斑斓色彩↵些许蒙上了年代感的色泽",
picUrl: "https://p2.music.126.net/NoURvJXsYoXrl1HqSoNy3Q==/109951165485850861.jpg",
},
];
const recommend = ({
name: 'recommend',
setup(props) {
const renderSpace = () => {
return (
<div class='spaceTitle'>
推荐歌单
</div>
)
};
const renderSwipe = () => {
return (
<van-swipe>
{
swipeMock.map(item => {
return (
<van-swipe-item key={item.id} class="swipeImg">
<img src={item.picUrl} alt=""/>
</van-swipe-item>
)
})
}
</van-swipe>
)
};
const renderRecommendList = () => {
return (
<div class="recommendList">
{
listMock.map((item) => {
return (
<div class="recommendItem" key={item.id}>
<img
src={item.picUrl}
alt=""/>
<div class="desc">
{item.name}
</div>
</div>
)
})
}
</div>
)
};
return() => (
<div className="recommendPage">
{ renderSwipe() }
{ renderSpace() }
{ renderRecommendList() }
</div>
)
},
});
export default recommend
最后一步: 新建src/view/recommend/index.scss
// 公共变量
$bgMain: #d44439;
$fontColor: #f1f1f1;
.recommendPage{
height: 100%;
background: #f2f2f2;
overflow-y: auto;
.swipeImg{
height: 160px;
width: 100%;
padding: 4px;
background-color: #fff;
img{
width: 100%;
height: 100%;
border-radius: 10px;
}
}
.spaceTitle{
font-weight: 700;
padding-left: 6px;
font-size: 14px;
line-height: 60px;
}
.recommendList{
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-around;
overflow-y: auto;
.recommendItem{
width: 32%;
img{
width: 100%;
height: 120px;
}
.desc{
overflow: hidden;
margin-top: 2px;
padding: 0 2px;
height: 50px;
text-align: left;
font-size: 12px;
line-height: 1.4;
color: #2E3030;
}
}
}
}
效果图:
这样就完成第一篇了~
JSX跟Vue3和Vant完美兼容的、希望有带来乐趣