VueCLI
- npm install nrm -g 安装 nrm 管理镜像
- nrm ls
- nrm use taobao
- npm install @vue/cli -g
- vue create my-app
- Please pick a preset
Manually select features - Check the features needed for your project: (Press <space> to select, <a> to t
oggle all, <i> to invert selection)
◉ Choose Vue version
◉ Babel
◯ TypeScript
◯ Progressive Web App (PWA) Support
◯ Router
◯ Vuex
◯ CSS Pre-processors
◉ Linter / Formatter
◯ Unit Testing
◯ E2E Testing - Choose a version of Vue.js that you want to start the project with
3.x (Preview) - Pick a linter / formatter config:
ESLint with error prevention only - Pick additional lint features: (Press to select, <a> to toggle all, <i> to invert selection)
Lint on save - Where do you prefer placing config for Babel, ESLint, etc.?
In dedicated config files - Save this as a preset for future projects?
n
单组件文件实现TodoList
<!-- App.vue -->
<template>
<div>
<input type="text" v-model="inputValue">
<button @click="handleAddItem">提交</button>
</div>
<ul>
<!-- <li :key="index" v-for="(item, index) in list">{{item}}</li> -->
<list-item :key="index" v-for="(item, index) in list" :item="item"/>
</ul>
</template>
<script>
import ListItem from './components/ListItem'
import { reactive, ref } from 'vue';
export default {
name: 'App',
components: {
ListItem
},
setup() {
const inputValue = ref('');
const list = reactive([]);
const handleAddItem = () => {
list.push(inputValue.value);
inputValue.value = '';
}
return {
inputValue,
list,
handleAddItem
}
}
}
</script>
<style>
</style>
<!-- components/ListItem.vue -->
<template>
<li>{{item}}</li>
</template>
<script>
export default {
name: 'ListItem',
props: {
item: String
}
}
</script>
<style>
</style>
路由加载
const routes = [
{
// 路由的同步加载
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 路由的异步加载,只有到页面真正访问到的时候才加载该页面的资源
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
路由跳转之前执行
// router/index.js
router.beforeEach((to/* 跳转向的路由 */, from/* 跳转来的路由 */, next /* 继续执行 */) => {
const isLogin = localStorage.getItem('isLogin')
(isLogin || to.name === 'Login') next() || next({ name: 'Login' })
})
单个路由跳转之前执行的函数
const routes = [
{
path: '/login',
name: 'Login',
component: Login,
beforeEnter(to, from, next) { // 与上面相同
const isLogin = localStorage.getItem('isLogin')
isLogin ? next({ name: 'Login' }) : next()
}
}
]
页面中路由跳转
// Login.vue
<script>
import { useRouter } from 'vue-router'
export default {
name: 'Login',
setup () {
const router = useRouter()
const handleLogin = () => {
localStorage.setItem('isLogin', true)
router.push({ name: 'Home' })
}
}
}
</script>
路由跳转上一个页面
import { useRouter } from 'vue-router'
export default {
name: 'Shop',
setup () {
const router = useRouter()
const handleBackClick = () => {
router.back()
}
}
}
链接路由跳转
<router-link to="/shop"></router-link>
<router-link :to="{name: 'Shop'}"></router-link>
VueX
// store/index.js
import { createStore } from 'vuex'
// VueX 数据管理框架
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据
export default createStore({
state: {
name: 'jack'
},
mutations: {
},
actions: {
},
modules: {
}
})
<!-- Home.vue -->
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
</div>
{{myName}}
</template>
<script>
export default {
name: 'Home',
computed: {
myName() {
return this.$store.state.name;
}
}
}
</script>
Vue 修改全局数据
<!-- About.vue -->
<template>
<div class="about">
<h1 @click="handleClick">This is an about page</h1>
{{myName}}
</div>
</template>
<script>
export default {
name: 'About',
computed: {
myName() {
return this.$store.state.name;
}
},
methods: {
handleClick() {
// 第一步:想改变数据,vuex 要求第一步,必须派发一个 action。
this.$store.dispatch('change');
}
}
}
</script>
// store/index.js
import { createStore } from 'vuex'
// VueX 数据管理框架
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据
export default createStore({
state: {
name: 'jack'
},
mutations: {
// 第四步,对应的 mutation 被执行
change() {
// 第五步,在 mutation 里面修改数据
this.state.name = 'tom';
}
},
actions: {
// 第二步: action 感知到你发出了一个叫做 change 的 action,执行 change action
change() {
// 第三步:提交一个 commit 触发一个 mutation
this.commit('change');
}
},
modules: {
}
})
Vue 通过传参修改变量
<!-- About.vue -->
<template>
<div class="about">
<h1 @click="handleClick">This is an about page</h1>
{{myName}}
</div>
</template>
<script>
export default {
name: 'About',
computed: {
myName() {
return this.$store.state.name;
}
},
methods: {
handleClick() {
// 想改变数据,vuex 要求第一步,必须派发一个 action。
this.$store.dispatch('change', 'hello world');
}
}
}
</script>
// store/index.js
import { createStore } from 'vuex'
// VueX 数据管理框架
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据
export default createStore({
state: {
name: 'jack'
},
// mutations 中不能使用异步代码,异步代码可放入 actions 中
// commit 和 mutation 做关联
mutations: {
change(state, str) {
state.name = str;
}
},
// dispatch 和 action 做关联
actions: {
change(store, str) {
store.commit('change', str);
}
},
modules: {
}
})
Composition API 实现 VueX
// About.vue
<template>
<div class="about">
<h1 @click="handleClick">This is an about page</h1>
{{name}}
</div>
</template>
<script>
import { useStore } from 'vuex';
import { toRefs } from 'vue';
export default {
name: 'About',
setup() {
const store = useStore();
const { name } = toRefs(store.state);
const handleClick = () => {
store.dispatch('change', 'hello');
}
return { name, handleClick };
}
}
</script>
// store/index.js
import { createStore } from 'vuex'
// VueX 数据管理框架
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据
export default createStore({
state: {
name: 'jack'
},
mutations: {
change(state, str) {
state.name = str;
}
},
actions: {
change(store, str) {
store.commit('change', str);
}
},
modules: {
}
})
css样式只在同一个组件种生效
使用 scoped
<style lang="scss" scoped>
</style>
vue 插件中 name 的作用
在 vue devtools 中显示的插件名为name,如果没有 name 插件会以文件名作为插件名显示,一般情况都会添加 name
<script>
export default {
name: 'StaticPart'
}
</script>