【一】ref属性
# ref也可以做组件间的通信
# ref是vue提供的属性,可以放在任意标签或组件上
- 如果放在标签上
-通过 this.$refs.标签上的名字 拿到的值是 标签 对象
-我们可以通过标签对象,修改 标签的属性。。。src属性,value属性
- 如果放在组件上
-通过 this.$refs.标签上的名字 拿到的值是 组件 对象
-我们可以通过 组件对象,直接修改对象中得数据,直接调用对象中得方法
【1】使用
(1)放在普通标签上
- 使用
this.$refs.ref对应的值
,就可以得到这个标签对象
<template>
<div>
<h1>ref的使用</h1>
<div>
<img :src="img" ref="my_img" style="height: 200px;width: 200px">
</div>
<div>
<input type="text" ref="my_input">
</div>
<button @click="handleSon">点击看控制台</button>
</div>
</template>
<script>
export default {
name:'one',
data(){
return{
// 这里他会检测不到这是个路径,需要一个方法require
img:require('../assets/img/1.png'),
}
},
methods:{
handleSon(){
// 获得img标签
console.log(this.$refs.my_img);
// 可以获得img的属性值
console.log(this.$refs.my_img.src);
// 还可以属性值
this.$refs.my_img.src=require('../assets/logo.png')
// 赋值
this.$refs.my_input.value='xxxx'
}
}
}
</script>
<style scoped>
</style>
【2】ref属性之父传子
-
父传子是自定义属性
-
父组件:
HOMEView.vue
<template>
<div class="home">
<h1>首页</h1>
<one :msg="my_data"></one>
</div>
</template>
<script>
import one from '@/components/one'
export default {
name: 'HomeView',
data(){
return{
my_data:'father'
}
},
components:{
one
}
}
</script>
- 子组件:
one.vue
<template>
<div>
<h1>ref的使用</h1>
<div>
<img :src="img" ref="my_img" style="height: 200px;width: 200px">
</div>
<!-- 使用父亲传过来的值 -->
<h2>{{msg}}</h2>
</div>
</template>
<script>
export default {
name:'one',
data(){
return{
// 这里他会检测不到这是个路径,需要一个方法require
img:require('../assets/img/1.png'),
}
},
props:["msg"]
}
</script>
<style scoped>
</style>
【3】ref属性之子传父
-
子传父是自定义事件:子的东西传给父亲,子里面肯定要有东西触发,在可以传给父
-
子传父:子组件中用到了,事件:
this.$emit("自定义事件名",传给父组件的值)
,父组件要接受这个值 -
父组件:
HOMEView.vue
<template>
<div class="home">
<h1>首页</h1>
<hr>
<one :msg="my_data" @son="my_father"></one>
<hr>
<h1>{{res}}</h1>
</div>
</template>
<script>
import one from '@/components/one'
export default {
name: 'HomeView',
data(){
return{
my_data:'father',
res:'',
}
},
methods:{
// 这里接受到子传过来的username
my_father(username){
this.res=username
}
},
components:{
one
}
}
</script>
- 子组件:
one.vue
<template>
<div>
<h1>ref的使用</h1>
<div>
<img :src="img" ref="my_img" style="height: 200px;width: 200px">
</div>
<!-- 使用父亲传过来的值 -->
<h2>{{msg}}</h2>
<!-- 子传父-->
<div>
<input type="text" v-model="username">
</div>
<button @click="handleSon">子传父</button>
</div>
</template>
<script>
export default {
name:'one',
data(){
return{
// 这里他会检测不到这是个路径,需要一个方法require
img:require('../assets/img/1.png'),
username:''
}
},
methods:{
handleSon(){
// 子传父
this.$emit("son",this.username)
}
},
props:["msg"]
}
</script>
<style scoped>
</style>
【补充】 父子通信的方式
# 子组件中拿到父组件对象
this.$parent
# 父子通信的方式
# 1 自定义属性
# 2 自定义事件
# 3 通过ref属性:this.$refs
# 4 子组件中通过 this.$parent
【二】props
- 功能:让组件接收外部传过来的数据
# props配置项是:子传父,自定义属性的时候用来接收父组件传给子组件的属性的,对应一个数组
# 方法一:
props=['msg']
# 方法二
- 这个意思是尽量的接收String类型的数据,会报错,但是不影响操作
props: {myname: String},
# 方法三
props: {
myname: {
type: String, //类型
required: true, //必要性
default: '老王' //默认值
}
},
【三】混入(mixin)
- 前言(js文件)
# 混入的意思是:抽取公共的代码
- 多个组件都在用的方法和属性,抽出来,做成公共的
- 那个组件用,使用mixin引入即可
# 有两种方式:我们可以叫做,局部使用和全局使用
- 使用
- 公共的组件
export default {
data() {
return {
username: '王一博'
}
},
methods: {
handleName(name) {
this.username = name
}
}
}
- 在其他组件中
局部
使用
<script>
// 可以使用多个
import m1 from '../mixin'
export default {
name: 'HomeView',
// 一定要写
data(){
return{
}
},
//一定要写
methods:{
},
mixins:[m1]
}
</script>
- 全局使用
# 全局使用 定义在main.js
import m1 from '@/mixin'
import m2 from '@/mixin2'
Vue.mixin(m1)
Vue.mixin(m2)
【四】插件
- 前言
# 插件的功能就是增强vue
# 插件使用者的意思就是:使用插件的时候串的值
Vue.user(ElementUI,'lsk')
# 本质就是:包含install方法的一个对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据
# 我们使用了:vue-router插件,vuex插件,elementui插件
- 有了这些插件,我们就可以使用:
this.$router
this.$store
# 弹框
this.$alert
this.$message
# 使用别人写好的插件:
- 首先记得引入
import ElementUI from 'element-ui';
Vue.user(ElementUI)
- 使用
# 存放到原型类中:prototype
- 注册
import m1 from '@/mixin'
import aaa from './pulgin'
Vue.use(aaa)
- 插件
export default {
install(Vue){
console.log(Vue)
// prototype原型类:就好比,你放在了一个最底层的代码中,别人用的时候他没有,就会往下 查,就会查到你定制进去的
// $age:名字随便定义,但是必须带$
Vue.prototype.$age='xxx'
// 你也可以将axios存放到原型类中
Vue.prototype.$ajax='axios'
// 你也可以添加路由
Vue.prototype.$BASE_URL='http://192.168.1.69:8080/'
}
}
- 在其他组件中使用
methods:{
handleName(){
// 就可以直接使用
// 就会渲染上去
this.age=this.$age
// 你发送axios请求,就可以这样
this.$ajax.get(this.$BASE_URL+'/login').then()
# 使用混入,这样我们就不用在main.js里面写了
Vue.mixin(m1)
#自定义指令---》可能会有第三方插件,在项目中使用后,会有没见过的指令
//定义全局指令:跟v-model一样,获取焦点
Vue.directive("fbind", {
//指令与元素成功绑定时(一上来)
bind(element, binding) {
element.value = binding.value;
},
//指令所在元素被插入页面时
inserted(element, binding) {
element.focus();
},
//指令所在的模板被重新解析时
update(element, binding) {
element.value = binding.value;
},
});
# 定义全局组件
- 好比elementui---》全局组件 <el-button>
- vue-router---->全局组件 <router-view/>
}
},
# 在main.js中使用,可以传参数
# 1 使用自定义插件
import my from '@/plugins'
Vue.use(my,'lsk') // 内部本质会执行install
- 你一旦传了参数
export default {
install(Vue,a){
console.log(a) # 就是lsk
}
# 咱们需要掌握的;
-有些第三方插件,用了以后,增强了vue功能
-this.$router
-全局组件 :el-button
-this.$message--->
-this.$http.get
【五】插槽
- 前言
# 让父组件可以向子组件指定位置插入html结构,也是一种组件间通信的方式,适用于 父组件 ===> 子组件
# 在小组件中使用:solt来显示你传的html结构的标签
- 使用
##########自定义的小组件
<template>
<div class="hello">
<slot name='one'></slot>
<h1>小组件HelloWorld</h1>
<slot name='two'></slot>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
}
</script>
<style scoped>
</style>
############使用
<template>
<div class="about">
<h1>About组件</h1>
<HelloWorld>
<!-- 在小组件中使用:solt,就会显示这张图片。这个你可以看作是传给小组件的图片,但是必须放在小组件中 -->
<div name='one'>
<img src="https://ts1.cn.mm.bing.net/th/id/R-C.987f582c510be58755c4933cda68d525?rik=C0D21hJDYvXosw&riu=http%3a%2f%2fimg.pconline.com.cn%2fimages%2fupload%2fupc%2ftx%2fwallpaper%2f1305%2f16%2fc4%2f20990657_1368686545122.jpg&ehk=netN2qzcCVS4ALUQfDOwxAwFcy41oxC%2b0xTFvOYy5ds%3d&risl=&pid=ImgRaw&r=0" alt="" style="height: 400px;width: 400px">
</div>
<div name='two'>
lllll
</div>
</HelloWorld>
</div>
</template>
<script>
import HelloWorld from "@/components/HelloWorld.vue";
export default {
template:'AboutView',
components:{
HelloWorld
}
}
</script>
【六】vuex
- 前言
# vuex是一个第三方插件:它叫状态管理器:统一位置管理变量---》也能实现组件间通信:页面刷新,会重置
- vue:vuex
- vue3:vuex,也有pina:用的多
# 使用vuex---》vuex的新版本支持vue3
-我们在创建项目时候,已经装了
-项目依赖有了
-项目中有个 store文件夹-->index.js
-main.js 中,引入且使用了
- 在创建项目时,没装
-我们要安装:
- 指定版本 cnpm install vuex@3.6.2 -S--->S是安装到你这个项目中,不加S的话,就是全局,别人用的时候,就会没有
- 在项目中新建 store包--》index.js文件
- 在index.js中写入代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
# 放变量
},
mutations: {
# 提交,修改就会触发(commit)
},
actions: {
# 调度就会触发(dispatch)
}
})
- 在main.js中使用
- 先引入
- import store from './store'
- 使用
new Vue({
store,
render: h => h(App)
}).$mount('#app')
- 使用
#####在组件中使用
<template>
<div>
<h1>首页</h1>
<h2>我们在state文件中的vuex插件中的count:{{$store.state.count}}</h2>
<button @click="handleCount">点击加1</button>
</div>
</template>
<script>
export default {
name: 'HomeView',
methods:{
handleCount(){
// 方式一
// 我们之间进行加1--->这样写不太安全
// this.$store.state.count++
// 方式二
// 我们先通知dispatch在通知commit,进行一系列操作
// dataAdd你定义在actions里面的方法
this.$store.dispatch('dataAdd')
// this.$store.commit('dataAdd')
}
}
}
</script>
- vuex插件
##############在store/index.js中代码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
// 这里面做加1
// 定义一个函数,随便起名字
// 这里回传一个变量
add(two){
two.count+=1
}
// 也可以在这里进行判断
},
actions: {
// 定义一个函数,随便起名字
// 这里回传一个变量
dataAdd(one){
// 通知mutations里面的对象add加1
// one.commit('add')
// 我们还可以进行判断
// one也可以拿到count
if (one.state.count >=5){
alert("太大了")
}else{
// 通知mutations里面的对象add加1
one.commit('add')
}
}
},
})
【1】重点
# 为什么经过 actions和mutations
- 可以跟后端交互,可以做数据验证
# getters
- 可以通过getters获取数据--》对state中的数据,再做处理
$store.getters.里面的方法
# modules
- 分到不同模块中,不同模块有自己的state,actions
【七】本地储存
- 前言
# 1 能存储数据的位置,登录成功---》token存储
vuex: 页面重新加载--》数据会恢复
# 过期时间
cookie:登录信息放这里,有过期时间,一旦过期,就没了
# 会话储存
sessionStorage:当前浏览器生效---》关闭浏览器,数据就没了
# 本地储存
localStorage:永久生效,除非代码删除或清空浏览器缓存
-未登录,加购物车
#2 vue中操作cookie 需要下载 vue-cookies
cnpm install vue-cookies -S
- 使用
<template>
<div>
<h1>首页</h1>
<h2>localStorage</h2>
<button @click="handleSaveLocalStorage">存储到localStorage</button>
<button @click="handleGetLocalStorage">从localStorage取出</button>
<button @click="handleDeleteLocalStorage">删除localStorage</button>
<h2>sessionStorage使用</h2>
<button @click="handleSavesessionStorage">存储到sessionStorage</button>
<button @click="handleGetsessionStorage">从sessionStorage取出</button>
<button @click="handleDeletesessionStorage">删除sessionStorage</button>
<h2>cookie使用</h2>
<button @click="handleSaveCookie">存储到cookie</button>
<button @click="handleGetCookie">从cookie取出</button>
<button @click="handleDeleteCookie">删除cookie</button>
</div>
</template>
<script>
export default {
name: 'HomeView',
methods: {
// 存储到localStorage中
handleSaveLocalStorage() {
localStorage.setItem("name", 'lqz')
let user = {
name: 'xxx',
age: 19
}
localStorage.setItem("user", JSON.stringify(user)) // 不要放对象
},
handleGetLocalStorage() {
let name = localStorage.getItem("name")
let user = localStorage.getItem('user')
console.log(name)
console.log(user)
console.log(typeof user)
},
handleDeleteLocalStorage() {
// 只会删除name
// localStorage.removeItem('name')
// 删除所有
localStorage.clear()
},
// 存储到sessionStorage中
handleSavesessionStorage() {
sessionStorage.setItem("name", '彭于晏')
},
handleGetsessionStorage() {
let name = sessionStorage.getItem('name')
console.log(name)
},
handleDeletesessionStorage() {
sessionStorage.removeItem('name')
// sessionStorage.clear()
},
// 存储到cookies中
// 必须下载 cnpm i vue-cookies -S
// 我们必须在main.js中引入
//import cookies from 'vue-cookies'
// 放在原型里
// Vue.prototype.$cookie = cookies;
handleSaveCookie() {
// 过期时间可以写1d,1h,1m
this.$cookies.set('name', 'zzzz', '100s')
},
handleGetCookie() {
let name = this.$cookies.get('name')
console.log(name)
},
handleDeleteCookie() {
this.$cookies.remove('name')
// 不可以删除所有,只可以指定
// this.$cookies.clear()
},
}
}
</script>
【八】vue-router
【1】router插件
# 1 如果我们创建项目时,已经安装了
-router--》index.js
-main.js 引入了
-后期在组件中使用:
-js中:
this.$router # 用来跳转路径
this.$route # 目前没学
-template中:
<router-view/> # 当访问某个路径时,会把页面组件替换到这
<router-link></router-link>
# 2 创建项目没有安装,自行引入
- 安装:cnpm install vue-router -S
-创建文件夹router---index.js
-index.js写代码
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from "@/views/HomeView";
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
-main.js中使用
import router from './router'
new Vue({
router,
render: h => h(App)
}).$mount('#app')
-后续所有组件中
-js中:
this.$router # 跳转路径
this.$route # 目前没学
-template中:
<router-view/> # 当访问某个路径时,会把页面组件替换到这
<router-link></router-link>
【2】路由跳转
# 1 之前学过,在App.vue中放
<div id="app">
<router-view/>
</div>
# 2 在router---index.js中--》注册路径-->routes
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
# 3 以后访问某个路径,就会显示页面组件
#4 重点:页面跳转两种方式
## 4.1 js跳转
# 1 传路径
// http://192.168.1.69:8080/about/
// this.$router.push('/about')
# 2 传对象
// http://192.168.1.69:8080/
// 这个name:就是你注册的时候的别名
// this.$router.push({'name': 'about'})
// path:就是你访问的路由
// this.$router.push({'path': '/about'})
# 3 携带参数跳转
// 系带参数访问
// this.$router.push('/about?name=lqz&age=19')
// 传对象,携带参数
// this.$router.push({'name': 'about',query:{name:'zhangsan',age:19}})
// 传对象,携带参数
this.$router.push({'path': '/about',query:{name:'zhangsan',age:19}})
# 4 template中跳转:使用:router-link组件
<router-link to="/about">
<button>点我跳转到about页面-router-link</button>
</router-link>
// 使用:router-link组件,传入对象的格式,携带的参数放在query中
<router-link :to="{name:'about',query:{name:'xxx'}}">
<button>点我跳转到about页面-router-link</button>
</router-link>
#5 重点 上个页面跳转时,携带数据(查询参数)---》下一个页面中取出来
-在下一个页面中写:AboutView.vue
-写在created中
created(){
# 比如你传的是id
this.book_id=this.$route.query['book_id']
#this.book_id=this.$route.query.book_id
#console.log(this.$router) // VueRouter 的对象
#console.log(this.$route) // 当前路由对象
}
# 6 重点 上个页面跳转时,携带数据(查询参数)---》下一个页面中取出来》》》转换器
6.1 路由写法变了
{
path: '/:pk/lqz',
name: 'lqz',
component: LQZView
},
6.2 传递数据
-js:
this.$router.push("/99/lqz")
this.$router.push({name:'lqz',params:{pk:666}})
-router-link:
<router-link to="/99/lqz">
<router-link :to="{name:'lqz',params:{pk:666}}">
6.3 另一个页面获取数据
this.$route.params.pk
【3】相关API--》router方法
1 指的是:this.$router--->方法
2 常用的
this.$router.push(path): 相当于点击路由链接(可以返回到当前路由界面)
this.$router.replace(path): 用新路由替换当前路由(不可以返回到当前路由界面)
this.$router.back(): 请求(返回)上一个记录路由
this.$router.go(-1): 请求(返回)上一个记录路由
this.$router.go(1): 请求下一个记录路由
【4】多级路由
# 就是可以分很多层的路由
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from "@/views/HomeView";
import AboutView from "@/views/AboutView";
import LQZView from "@/views/LQZView";
import MulRouterView from "@/views/MulRouterView";
import IndexView from "../../src_昨日/views/pages/IndexView";
import OrderView from "../../src_昨日/views/pages/OrderView";
import GoodsView from "../../src_昨日/views/pages/GoodsView";
Vue.use(VueRouter,)
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/mul',
name: 'mul',
component: MulRouterView,
children: [ //通过children配置子级路由
{
path: '', //此处一定不要写:/news
name:'index',
component: IndexView
},
{
path: 'order',
name:'order',
component: OrderView
},
{
path: 'goods',
component: GoodsView
}
]
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
MulRouterView.vue
pages
GoodsView.vue
IndexView.vue
OrderView.vue
- MulRouterView.vue
<template>
<div>
<div style="height: 80px;background-color: pink"></div>
<el-container>
<el-aside width="200px">
<div style="background-color:greenyellow;height:700px ">
<!-- 多级路由-->
<p><router-link to="/mul">首页</router-link></p>
<!-- 多级路由---也可以指定别名-->
<p><router-link :to="{name:'order'}">订单</router-link></p>
<!-- 多级路由---直接锁定根路由-->
<p><router-link to="/mul/goods">商品</router-link></p>
</div>
</el-aside>
<el-container>
<el-header>
<div style="background-color:rebeccapurple"></div>
</el-header>
<el-main>
<div style="height:500px;background-color: aqua">
<router-view></router-view>
</div>
</el-main>
<el-footer>
<div style="background-color: pink;height:50px"></div>
</el-footer>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "MulRouterView"
}
</script>
<style scoped>
</style>
pages-- GoodsView.vue
<template>
<div>
<h1>商品</h1>
</div>
</template>
<script>
export default {
name: "GoodsView"
}
</script>
<style scoped>
</style>
pages-- IndexView.vue
<template>
<div>
<h1>后台首页</h1>
</div>
</template>
<script>
export default {
name: "IndexView"
}
</script>
<style scoped>
</style>
pages–OrderView.vue
<template>
<div>
<h1>订单</h1>
</div>
</template>
<script>
export default {
name: "OrderView"
}
</script>
<style scoped>
</style>
【5】路由守护
- 前言
# 路由守护:就是字面的意思,守护路由
# 就比如:你需要登才可以访问的页面
# 守护路由:全局守护,独享守护,组件内守护
# 我们用到的最多的就是全局守护
- 使用
router/index.js
// 配置全局的路由守卫
router.beforeEach((to, from, next) => {
// to:要去的路由的对象,from:来自那个路由的对象,next:跳转到那个路径
// 要去的路径,如果不是登入路径和/根路径,要判断有没有登入,登录的token存入到localStorage中
// 这里的name就是你路由中的别名,path就是你路由中的真正路由地址
if (to.name == 'login' || to.path == '/') {
// 直接跳转
next()
}else{
// 判断有没有登录,取token
let token = localStorage.getItem('token')
// 在进行判断token
if (token){
// 存在直接跳转
next()
}else{
// 使用Message需要导入Element
// 这是一个好看的弹框
Element.Message.error('请先登录!!')
// 跳转到等于页面
next({name:'login'})
}
}
})
【6】路由的两种工作模式
- Hash模式
// URL 示例: http://192.168.1.69:8080/#/login
// 特点: 使用 URL 的 hash (#) 部分来表示路由。浏览器不会发送 hash 部分到服务器,所以页面刷新时不会向服务器发起请求。
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Element from 'element-ui'
Vue.use(VueRouter)
// 路由配置
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
const router = new VueRouter({
mode: 'hash', // 使用 hash 模式
base: process.env.BASE_URL, // 基础路径
routes // 路由配置
})
// 配置全局的路由守卫
router.beforeEach((to, from, next) => {
....
})
export default router
- History 模式:
// URL 示例: http://192.168.1.69:8080/login
// 特点: 使用 HTML5 History API 来管理 URL,使 URL 看起来更干净和自然。需要服务器支持,通常需配置服务器以处理所有请求并返回应用的入口 HTML 文件。
// 配置方式:
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Element from 'element-ui'
Vue.use(VueRouter)
// 路由配置
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
const router = new VueRouter({
mode: 'history', // 使用 history 模式
base: process.env.BASE_URL, // 基础路径
routes // 路由配置
})
// 配置全局的路由守卫
router.beforeEach((to, from, next) => {
....
})
export default router
- 总结
选择哪一个:
如果你希望 URL 更加干净和现代,并且可以配置服务器来支持此模式,则选择 history 模式。
如果你需要兼容旧浏览器或无法配置服务器,则选择 hash 模式。
【九】scoped样式
# 作用:让样式在局部生效,防止冲突。
# 写法:<style scoped>
component: HomeView
},
]
const router = new VueRouter({
mode: ‘hash’, // 使用 hash 模式
base: process.env.BASE_URL, // 基础路径
routes // 路由配置
})
// 配置全局的路由守卫
router.beforeEach((to, from, next) => {
…
})
export default router
- **History 模式**:
```js
// URL 示例: http://192.168.1.69:8080/login
// 特点: 使用 HTML5 History API 来管理 URL,使 URL 看起来更干净和自然。需要服务器支持,通常需配置服务器以处理所有请求并返回应用的入口 HTML 文件。
// 配置方式:
import Vue from 'vue'
import VueRouter from 'vue-router'
import HomeView from '../views/HomeView.vue'
import Element from 'element-ui'
Vue.use(VueRouter)
// 路由配置
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
]
const router = new VueRouter({
mode: 'history', // 使用 history 模式
base: process.env.BASE_URL, // 基础路径
routes // 路由配置
})
// 配置全局的路由守卫
router.beforeEach((to, from, next) => {
....
})
export default router
```
- 总结
````python
选择哪一个:
如果你希望 URL 更加干净和现代,并且可以配置服务器来支持此模式,则选择 history 模式。
如果你需要兼容旧浏览器或无法配置服务器,则选择 hash 模式。
【九】scoped样式
# 作用:让样式在局部生效,防止冲突。
# 写法:<style scoped>