vue 基础学习
一、ref 和reactive 区别
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><h1>{{Web.title}}</h1><h1>{{Web.url}}</h1><h1>{{msg}}</h1><h1>{{number}}</h1><h1>{{arr}}</h1>
</div><script type="module">import {createApp, ref, reactive} from "./vue.esm-browser.js";createApp({setup() {const number = ref(10) //ref 用于存储单个基本数据类型的数据,如数字,字符串number.value = 20 // 使用ref 创建的响应式对象,需要通过.value 属性来访问和修改其值const arr = [1, 2, 3]const Web = reactive({title: "码农编程进阶笔记",url: "www.baidu.com"})Web.url = "www.sina.com"return {msg: "success",Web,number, arr}}}).mount('#app')
</script>
</body>
</html>
问题:发生跨域问题
Access to script at 'file:///Users/new/Desktop/webroot/vue/vue.esm-browser.js' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: chrome, chrome-extension, chrome-untrusted, data, http, https, isolated-app.
这个报错表明你遇到了跨域相关的问题,以下是对该报错的详细分析以及解决办法:
报错原因
当你在浏览器中直接通过 file://
协议(本地文件协议)去加载一个 JavaScript 文件(这里是 vue.esm-browser.js
),并且该文件中的代码尝试进行一些跨域相关的操作(比如加载其他资源、发起 Ajax 请求等,虽然在你这个例子里可能只是模块加载的情况,但本质上涉及到了同源策略的限制)时,浏览器的同源策略就会起作用。
同源策略要求协议、域名和端口都要相同才允许进行资源交互,而 file://
协议下的页面被认为是没有明确的 “源”(origin
为 null
),它与正常的网络请求所遵循的 http
、https
等协议的交互机制不同,浏览器默认是禁止 file://
协议下的跨域操作的,所以就会出现被 CORS(跨域资源共享)政策阻止的情况,提示只支持 chrome
、chrome-extension
、chrome-untrusted
、data
、http
、https
、isolated-app
这些协议方案下的跨域请求。
解决办法
以下是几种常见的解决思路:
1. 使用本地服务器来运行项目
- 原理:
将项目通过本地服务器(比如基于 Node.js 的http-server
、live-server
等工具,或者使用集成开发环境自带的服务器功能,如 WebStorm 等 IDE 可以方便地启动本地服务器)以http
协议来运行,这样就符合了浏览器跨域策略中支持的协议类型,能避免file://
协议带来的跨域限制问题。 - 示例操作(以
http-server
为例):- 首先确保已经安装了
http-server
,如果没安装,可以通过npm install -g http-server
(全局安装,前提是已经安装了 Node.js 和 npm)命令来安装。 - 打开命令行,进入到包含
vue.esm-browser.js
文件的项目根目录(例如在你的例子中就是/Users/new/Desktop/webroot/vue/
这个目录),然后运行http-server
命令。 - 之后
http-server
会启动并显示一个本地的访问地址(一般是类似http://localhost:8080
这样的形式,端口可能会根据实际情况不同),通过浏览器访问这个地址来查看你的项目,此时应该就不会出现上述跨域报错了,因为模块加载等操作都在http
协议下进行,符合跨域策略要求。
- 首先确保已经安装了
2. 配置浏览器允许跨域访问本地文件(不太推荐,存在安全风险)
- 原理:
对于一些特定的浏览器(如 Chrome),可以通过设置一些特定的启动参数或者安装扩展来放宽对本地文件跨域访问的限制,但这种方式会降低浏览器的安全性,因为它绕过了原本的安全策略,所以一般只建议在开发测试环境且明确知晓风险的情况下使用。 - 示例操作(以 Chrome 为例):
- 方法一:使用命令行参数启动
在终端中通过添加--disable-web-security
和--user-data-dir
参数来启动 Chrome,例如(在 macOS 或 Linux 下):
- 方法一:使用命令行参数启动
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --disable-web-security --user-data-dir=/tmp/chromeTemp
(在 Windows 下类似地找到 Chrome 的可执行文件路径并添加参数启动),不过这种方式每次启动 Chrome 都需要这样操作,不太方便。
- 方法二:使用扩展(有一些专门用于开发时临时解决跨域问题的扩展,如
Allow CORS: Access-Control-Allow-Origin
等)
先在 Chrome 网上应用店中搜索安装这类扩展,安装后在扩展的设置中启用对本地文件的跨域访问权限等相关配置,这样在使用 Chrome 访问本地文件时就可能绕过跨域限制了,但要记得在正式环境不要使用这类扩展,避免安全隐患。
总之,推荐优先采用使用本地服务器运行项目的方式来解决这个问题,既能保证安全性,又符合正常的网页开发和跨域规范。
二、绑定事件
<!DOCTYPE html>
<html lang="en" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><h1>{{Web.title}}</h1><h1>{{Web.url}}</h1><h1>{{Web.user}}</h1><button v-on:click="edit">修改</button><button @click="edit">修改-简写形式@</button><hr>回车 <input type="text" @keyup.enter="add(40,60)"><br>空格 <input type="text" @keyup.space="add(10,20)"><br>Tab <input type="text" @keydown.tab="add(20,20)"><br>W <input type="text" @keyup.w="add(1,2)"><br><!-- 组合快捷键-->Ctrl+Enter <input type="text" @keyup.ctrl.enter="add(40,60)"><br>Ctrl+A <input type="text" @keyup.ctrl.a="add(40,60)"><br>
</div><script type="module">import {createApp, reactive} from "./vue.esm-browser.js";createApp({setup() {const Web = reactive({title: '码农编程进阶笔记',url: "http://www.baidu.com",user: 0})const edit = () => {Web.url = 'www.sina.com'}const add = (a, b) => {Web.user += a + b}return {msg: "success",Web,add,edit}}}).mount("#app")</script>
</body>
</html>
三、显示与隐藏
1. 显示和隐藏:v-show
2. 条件渲染 v-if
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<div id="app"><h3>{{web.show}}</h3><p v-show="web.show"> 码农编程进阶笔记</p><p v-if="web.show"> 笔记</p><button @click="toggle">点击切换显示状态</button><p v-if="web.user<1000">新网站</p><p v-else-if="web.user>=1000 && web.user<=10000">优秀网站</p><p v-else-if="web.user>=10000 && web.user<=100000">资深网站</p><p v-else>超级网站</p>
</div>
<script type="module">/*** v-show 通过css display 属性来控制元素的显示与隐藏* v-if 用于对元素进行条件渲染,当天条件为true时则渲染,条件为false时,则不渲染** v-show 用于频繁切换元素的显示状态,因为只改变display 属性,不需要重新渲染整个组件* v-if 用于较少改变的场景,因为频繁从dom中删除和增加元素,会导致性能下降*/// import {createApp, reactive} from "./vue.esm-browser.js";import {createApp, reactive} from "./vue.esm-browser.js";createApp({setup() {const web = reactive({show: true,user: 500111})// 切换按钮const toggle = () => {web.show = !web.show}return {msg: "success",toggle,web}}}).mount("#app")</script></body>
</html>
v-show 显示和隐藏
3.动态绑定 v-bind
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<style>.textColor {color: aqua;}
</style>
<body><div id="app"><!--:value--><h3>v-bind:value="web.url"</h3><input type="text" v-bind:value="web.url"><h3>简写 :value="web.url"</h3><input type="text" :value="web.url"><!--:src--><h3>v-bind:src</h3><img v-bind:src="web.image"><h3>简写:src</h3><img :src="web.image"><!--:class--><h3>v-bind:class</h3><b class="textColor">测试OK</b><h3>根据fontStatus动态class:class</h3><b :class="{textColor:web.fontStatus}"> 测试OK</b>
</div><script type="module">import {createApp, reactive} from "./vue.esm-browser.js";createApp({setup() {const web = reactive({url: "baidu.com",image: "./1.png",fontStatus: true})return {web}}}).mount("#app");
</script>
</body>
</html>
4.循环 v-for
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><ul><li v-for="value in data.number">{{value}}</li></ul><ul><li v-for="(value,index) in data.number">index:{{index}} ==> value:{{value}}</li></ul><ul><li v-for="(value,key,index) in data.user">index -索引:{{index}} ==> key键:{{key}} ==> value值:{{value}}</li></ul><ul><template v-for="(value,key,index) in data.user"><li v-if="index==1">index -索引:{{index}} ==> key键:{{key}} ==> value值:{{value}}</li></template></ul><ul><li v-for="(item,index) in data.teacher" :title="item.name" :key="item.id">index:{{index}} ==> id:{{item.id}} ==> name:{{item.name}} ==> age:{{item.age}}</li></ul></div>
<script type="module">import {createApp, reactive} from "./vue.esm-browser.js";createApp({setup() {const data = reactive({number: ["十", '十一', '十二'], //数组user: { //对象name: 'lxw',sex: '男'},teacher: [ //包含两个对象的数组{'id': 1, 'name': 'lxw3', 'age': 22},{'id': 2, 'name': 'lxw4', 'age': 42},]})return {data}}}).mount("#app")
</script>
</body>
</html>
5. 双向绑定v-model
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><div id="app"><h3>文本框 {{data.text}} </h3><h3>单选框 {{data.radio}} </h3><h3>复选框 {{data.checkbox}} </h3><h3>记住密码框 {{data.remember}} </h3><h3>下拉框 {{data.select}} </h3><!--单项数据绑定:当数据发生变化时,视图会自动更新,但用户手动更改input的值,数据不会自动更新 -->单项数据绑定 <input type="text" :value="data.text"/> <br><!-- 双向数据绑定:当数据发生变化时,视图会自动更新,当用户手动更改input的值,数据也会自动更新--><!-- 对于<input type="text">,v-model 绑定的是input 的value属性 -->双向数据绑定 <input type="text" v-model="data.text"><br>
<!-- 对于单选框,v-model 绑定的是input 元素的选中状态 -->单选框:<input type="radio" v-model="data.radio" value="1">英语<input type="radio" v-model="data.radio" value="2">数学<br><!-- 对于复选框,v-model 绑定的是input 元素的选中状态 -->复选框:<input type="checkbox" v-model="data.checkbox" value="A">英语<input type="checkbox" v-model="data.checkbox" value="B">数学<input type="checkbox" v-model="data.checkbox" value="C">语文<br><input type="checkbox" v-model="data.remember" >记住密码<br><!-- 对于<select>,v-model 绑定的是input 元素的选中状态 --><select v-model="data.select"><option value="">请选择</option><option value="A">英语</option><option value="B">语文</option><option value="C">数学</option></select></div><script type="module">import {createApp, reactive} from "./vue.esm-browser.js";createApp({setup() {const data = reactive({text: "baidu.com", //文本框radio: "",//单选框checkbox: [],//复选框remember: false,//单个复选框-记住密码select: "",})return {data}}}).mount("#app")
</script>
</body>
</html>